[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-Text-MultiLanguage.cpp
1 /*
2  * Copyright (c) 2023 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 <unistd.h>
21
22 #include <dali/devel-api/text-abstraction/font-client.h>
23 #include <dali-toolkit/internal/text/character-set-conversion.h>
24 #include <dali-toolkit/internal/text/logical-model-impl.h>
25 #include <dali-toolkit/internal/text/multi-language-helper-functions.h>
26 #include <dali-toolkit/internal/text/multi-language-support.h>
27 #include <dali-toolkit/internal/text/multi-language-support-impl.h>
28 #include <dali-toolkit/internal/text/segmentation.h>
29 #include <dali-toolkit/internal/text/text-run-container.h>
30 #include <dali-toolkit-test-suite-utils.h>
31 #include <dali-toolkit/dali-toolkit.h>
32
33 using namespace Dali;
34 using namespace Toolkit;
35 using namespace Text;
36
37
38 // Tests the following functions with different scripts.
39 //
40 // void MergeFontDescriptions(const Vector<FontDescriptionRun>&       fontDescriptions,
41 //                            const TextAbstraction::FontDescription& defaultFontDescription,
42 //                            TextAbstraction::PointSize26Dot6        defaultPointSize,
43 //                            float                                   fontSizeScale,
44 //                            CharacterIndex                          characterIndex,
45 //                            TextAbstraction::FontDescription&       fontDescription,
46 //                            TextAbstraction::PointSize26Dot6&       fontPointSize,
47 //                            bool&                                   isDefaultFont);
48 //
49 // Script GetScript(Length                                  index,
50 //                  Vector<ScriptRun>::ConstIterator&       scriptRunIt,
51 //                  const Vector<ScriptRun>::ConstIterator& scriptRunEndIt);
52 //
53 // Constructor, destructor and MultilanguageSupport::Get()
54 //
55 // void MultilanguageSupport::SetScripts(const Vector<Character>& text,
56 //                                       CharacterIndex           startIndex,
57 //                                       Length                   numberOfCharacters,
58 //                                       Vector<ScriptRun>&       scripts);
59 //
60 // void MultilanguageSupport::ValidateFonts(const Vector<Character>&                text,
61 //                                          const Vector<ScriptRun>&                scripts,
62 //                                          const Vector<FontDescriptionRun>&       fontDescriptions,
63 //                                          const TextAbstraction::FontDescription& defaultFontDescription,
64 //                                          TextAbstraction::PointSize26Dot6        defaultFontPointSize,
65 //                                          float                                   fontSizeScale,
66 //                                          CharacterIndex                          startIndex,
67 //                                          Length                                  numberOfCharacters,
68 //                                          Vector<FontRun>&                        fonts);
69
70 //////////////////////////////////////////////////////////
71
72 namespace
73 {
74
75 const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
76 const unsigned int EMOJI_FONT_SIZE = 3840u; // 60 * 64
77 const unsigned int NON_DEFAULT_FONT_SIZE = 40u;
78
79 struct MergeFontDescriptionsData
80 {
81   std::string description;                                 ///< Description of the experiment.
82   Vector<FontDescriptionRun> fontDescriptionRuns;          ///< The font description runs.
83   TextAbstraction::FontDescription defaultFontDescription; ///< The default font description.
84   TextAbstraction::PointSize26Dot6 defaultPointSize;       ///< The default point size.
85   float        fontSizeScale;                              ///< The font's size scale.
86   unsigned int startIndex;                                 ///< The start index.
87   unsigned int numberOfCharacters;                         ///< The number of characters.
88   Vector<FontId> expectedFontIds;                          ///< The expected font ids.
89   Vector<bool> expectedIsDefault;                          ///< The expected font ids.
90 };
91
92 struct ScriptsData
93 {
94   std::string description;         ///< Description of the experiment.
95   std::string text;                ///< Input text.
96   unsigned int index;              ///< The index of the first character to update the script.
97   unsigned int numberOfCharacters; ///< The numbers of characters to update the script.
98   Vector<ScriptRun> scriptRuns;    ///< Expected script runs.
99 };
100
101 struct ValidateFontsData
102 {
103   std::string                description;         ///< Description of the experiment.
104   std::string                text;                ///< Input text.
105   std::string                defaultFont;         ///< The default font.
106   unsigned int               defaultFontSize;     ///< The default font size.
107   float                      fontSizeScale;       ///< The font's size scale.
108   unsigned int               index;               ///< The index of the first character to update the script.
109   unsigned int               numberOfCharacters;  ///< The numbers of characters to update the script.
110   Vector<FontDescriptionRun> fontDescriptionRuns; ///< The font description runs.
111   Vector<FontRun>            fontRuns;            ///< The expected font runs.
112 };
113
114 //////////////////////////////////////////////////////////
115 bool MergeFontDescriptionsTest( const MergeFontDescriptionsData& data )
116 {
117   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
118
119   Vector<FontId> fontIds;
120   fontIds.Resize( data.startIndex + data.numberOfCharacters, 0u );
121   Vector<bool> isDefaultFont;
122   isDefaultFont.Resize( data.startIndex + data.numberOfCharacters, true );
123
124   for( unsigned int index = data.startIndex; index < data.startIndex + data.numberOfCharacters; ++index )
125   {
126     TextAbstraction::FontDescription fontDescription;
127     TextAbstraction::PointSize26Dot6 fontPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
128
129     MergeFontDescriptions( data.fontDescriptionRuns,
130                            data.defaultFontDescription,
131                            data.defaultPointSize,
132                            data.fontSizeScale,
133                            index,
134                            fontDescription,
135                            fontPointSize,
136                            isDefaultFont[index] );
137
138     if( !isDefaultFont[index] )
139     {
140       fontIds[index] = fontClient.GetFontId( fontDescription, fontPointSize );
141     }
142   }
143
144   if( fontIds.Count() != data.expectedFontIds.Count() )
145   {
146     std::cout << data.description << " Different number of font ids : " << fontIds.Count() << ", expected : " << data.expectedFontIds.Count() << std::endl;
147     return false;
148   }
149
150   for( unsigned int index = 0u; index < fontIds.Count(); ++index )
151   {
152     if( fontIds[index] != data.expectedFontIds[index] )
153     {
154       std::cout << data.description << " Different font id at index : " << index << ", font id : " << fontIds[index] << ", expected : " << data.expectedFontIds[index] << std::endl;
155       std::cout << "           font ids : ";
156       for( unsigned int i=0;i<fontIds.Count();++i)
157       {
158         std::cout << fontIds[i] << " ";
159       }
160       std::cout << std::endl;
161       std::cout << "  expected font ids : ";
162       for( unsigned int i=0;i<data.expectedFontIds.Count();++i)
163       {
164         std::cout << data.expectedFontIds[i] << " ";
165       }
166       std::cout << std::endl;
167       return false;
168     }
169
170     if( isDefaultFont[index] != data.expectedIsDefault[index] )
171     {
172       std::cout << data.description << " Different 'is font default' at index : " << index << ", is font default : " << isDefaultFont[index] << ", expected : " << data.expectedIsDefault[index] << std::endl;
173       return false;
174     }
175   }
176
177   return true;
178 }
179
180 bool ScriptsTest( const ScriptsData& data )
181 {
182   MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
183
184   // 1) Convert to utf32
185   Vector<Character> utf32;
186   utf32.Resize( data.text.size() );
187
188   const uint32_t numberOfCharacters = ( data.text.size() == 0 ) ? 0 :
189     Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
190                  data.text.size(),
191                  &utf32[0u] );
192
193   utf32.Resize( numberOfCharacters );
194
195   // 2) Set the script info.
196   Vector<ScriptRun> scripts;
197   multilanguageSupport.SetScripts( utf32,
198                                    0u,
199                                    numberOfCharacters,
200                                    scripts );
201
202   if( ( 0u != data.index ) ||
203       ( numberOfCharacters != data.numberOfCharacters ) )
204   {
205     // 3) Clear the scripts.
206     ClearCharacterRuns( data.index,
207                         data.index + data.numberOfCharacters - 1u,
208                         scripts );
209
210     multilanguageSupport.SetScripts( utf32,
211                                      data.index,
212                                      data.numberOfCharacters,
213                                      scripts );
214   }
215
216   // 4) Compare the results.
217
218   tet_printf( "Testing %s\n", data.description.c_str() );
219   if( scripts.Count() != data.scriptRuns.Count() )
220   {
221     tet_printf("ScriptsTest FAIL: different number of scripts. %d, should be %d\n", scripts.Count(), data.scriptRuns.Count() );
222     for( Vector<ScriptRun>::ConstIterator it = scripts.Begin(); it != scripts.End(); ++it)
223     {
224       const ScriptRun& run = *it;
225
226       std::cout << "  index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", script : [" << TextAbstraction::ScriptName[run.script] << "]" << std::endl;
227     }
228     return false;
229   }
230
231   for( unsigned int index = 0u; index < scripts.Count(); ++index )
232   {
233     const ScriptRun& scriptRun1 = scripts[index];
234     const ScriptRun& scriptRun2 = data.scriptRuns[index];
235
236     if( scriptRun1.characterRun.characterIndex != scriptRun2.characterRun.characterIndex )
237     {
238       tet_printf("ScriptsTest FAIL: different character index. %d, should be %d\n", scriptRun1.characterRun.characterIndex, scriptRun2.characterRun.characterIndex );
239       return false;
240     }
241
242     if( scriptRun1.characterRun.numberOfCharacters != scriptRun2.characterRun.numberOfCharacters )
243     {
244       tet_printf("ScriptsTest FAIL: different number of characters. %d, should be %d\n", scriptRun1.characterRun.numberOfCharacters, scriptRun2.characterRun.numberOfCharacters );
245       return false;
246     }
247
248     if( scriptRun1.script != scriptRun2.script )
249     {
250       tet_printf("ScriptsTest FAIL: script index: %u, different script. %s, should be %s\n", index, TextAbstraction::ScriptName[scriptRun1.script], TextAbstraction::ScriptName[scriptRun2.script] );
251       return false;
252     }
253   }
254
255   return true;
256 }
257
258 bool ValidateFontTest( const ValidateFontsData& data )
259 {
260   MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
261   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
262
263   // 1) Convert to utf32
264   Vector<Character> utf32;
265   utf32.Resize( data.text.size() );
266
267   const uint32_t numberOfCharacters = (data.text.size() == 0 ) ? 0 :
268     Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
269                                                    data.text.size(),
270                                                    &utf32[0u] );
271   utf32.Resize( numberOfCharacters );
272
273   // 2) Set the script info.
274   Vector<ScriptRun> scripts;
275   multilanguageSupport.SetScripts( utf32,
276                                    0u,
277                                    numberOfCharacters,
278                                    scripts );
279
280   char* pathNamePtr = get_current_dir_name();
281   const std::string pathName( pathNamePtr );
282   free( pathNamePtr );
283
284   // Get the default font id.
285   const FontId defaultFontId = fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + data.defaultFont,
286                                                      data.defaultFontSize );
287   TextAbstraction::FontDescription defaultFontDescription;
288   fontClient.GetDescription( defaultFontId, defaultFontDescription );
289
290   const TextAbstraction::PointSize26Dot6 defaultPointSize = fontClient.GetPointSize( defaultFontId );
291
292   Vector<FontRun> fontRuns;
293
294   // 3) Validate the fonts.
295   multilanguageSupport.ValidateFonts( utf32,
296                                       scripts,
297                                       data.fontDescriptionRuns,
298                                       defaultFontDescription,
299                                       defaultPointSize,
300                                       data.fontSizeScale,
301                                       0u,
302                                       numberOfCharacters,
303                                       fontRuns );
304
305   if( ( 0u != data.index ) ||
306       ( numberOfCharacters != data.numberOfCharacters ) )
307   {
308     // 4) Clear the fonts.
309     ClearCharacterRuns( data.index,
310                         data.index + data.numberOfCharacters - 1u,
311                         fontRuns );
312
313     multilanguageSupport.ValidateFonts( utf32,
314                                         scripts,
315                                         data.fontDescriptionRuns,
316                                         defaultFontDescription,
317                                         defaultPointSize,
318                                         data.fontSizeScale,
319                                         data.index,
320                                         data.numberOfCharacters,
321                                         fontRuns );
322   }
323
324   // 5) Compare the results.
325   if( data.fontRuns.Count() != fontRuns.Count() )
326   {
327     std::cout << "  Different number of font runs : " << fontRuns.Count() << ", expected : " << data.fontRuns.Count() << std::endl;
328     return false;
329   }
330
331
332   for( unsigned int index = 0; index < data.fontRuns.Count(); ++index )
333   {
334     const FontRun& run = fontRuns[index];
335     const FontRun& expectedRun = data.fontRuns[index];
336
337     if( run.characterRun.characterIndex != expectedRun.characterRun.characterIndex )
338     {
339       std::cout << "  character run : " << index << ", index : " << run.characterRun.characterIndex << ", expected : " << expectedRun.characterRun.characterIndex << std::endl;
340       return false;
341     }
342     if( run.characterRun.numberOfCharacters != expectedRun.characterRun.numberOfCharacters )
343     {
344       std::cout << "  character run : " << index << ", num chars : " << run.characterRun.numberOfCharacters << ", expected : " << expectedRun.characterRun.numberOfCharacters << std::endl;
345       return false;
346     }
347     if( run.fontId != expectedRun.fontId )
348     {
349       std::cout << "  character run : " << index << ", font : " << run.fontId << ", expected : " << expectedRun.fontId << std::endl;
350       return false;
351     }
352   }
353
354   return true;
355 }
356
357 } // namespace
358
359 int UtcDaliTextGetScript(void)
360 {
361   ToolkitTestApplication application;
362   tet_infoline(" UtcDaliTextGetScript");
363
364   Script script = TextAbstraction::LATIN;
365
366   // Text with no scripts.
367   Vector<ScriptRun> scriptRuns;
368   Vector<ScriptRun>::ConstIterator scriptRunIt = scriptRuns.Begin();
369   script = GetScript( 0u,
370                       scriptRunIt,
371                       scriptRuns.End() );
372
373   DALI_TEST_CHECK( TextAbstraction::UNKNOWN == script );
374
375   const unsigned int numberOfCharacters = 7u;
376   // Add scripts.
377   ScriptRun scriptRun01 =
378   {
379     {
380       0u,
381       2u,
382     },
383     TextAbstraction::LATIN
384   };
385   ScriptRun scriptRun02 =
386   {
387     {
388       2u,
389       2u,
390     },
391     TextAbstraction::HEBREW
392   };
393   ScriptRun scriptRun03 =
394   {
395     {
396       4u,
397       2u,
398     },
399     TextAbstraction::ARABIC
400   };
401   scriptRuns.PushBack( scriptRun01 );
402   scriptRuns.PushBack( scriptRun02 );
403   scriptRuns.PushBack( scriptRun03 );
404
405   // Expected results
406   TextAbstraction::Script expectedScripts[]=
407   {
408     TextAbstraction::LATIN,
409     TextAbstraction::LATIN,
410     TextAbstraction::HEBREW,
411     TextAbstraction::HEBREW,
412     TextAbstraction::ARABIC,
413     TextAbstraction::ARABIC,
414     TextAbstraction::UNKNOWN
415   };
416
417   scriptRunIt = scriptRuns.Begin();
418   for( unsigned int index = 0u; index < numberOfCharacters; ++index )
419   {
420     script = GetScript( index,
421                         scriptRunIt,
422                         scriptRuns.End() );
423
424     DALI_TEST_CHECK( expectedScripts[index] == script );
425   }
426   DALI_TEST_CHECK( scriptRunIt == scriptRuns.End() );
427
428   tet_result(TET_PASS);
429   END_TEST;
430 }
431
432 int UtcDaliTextMergeFontDescriptions(void)
433 {
434   ToolkitTestApplication application;
435   tet_infoline(" UtcDaliTextMergeFontDescriptions");
436
437   // Load some fonts.
438
439   char* pathNamePtr = get_current_dir_name();
440   const std::string pathName( pathNamePtr );
441   free( pathNamePtr );
442
443   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
444   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf" );
445   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif.ttf" );
446   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif.ttf", NON_DEFAULT_FONT_SIZE );
447   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif-Bold.ttf" );
448   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif-Italic.ttf" );
449
450   // To test the font width as GetFontId() with the font file path can't cache the width property.
451   TextAbstraction::FontDescription widthDescription;
452   widthDescription.path = "";
453   widthDescription.family = "DejaVu Serif";
454   widthDescription.weight = TextAbstraction::FontWeight::NORMAL;
455   widthDescription.width = TextAbstraction::FontWidth::EXPANDED;
456   widthDescription.slant = TextAbstraction::FontSlant::NORMAL;
457   fontClient.GetFontId( widthDescription );
458
459   // Test.
460
461   TextAbstraction::FontDescription defaultFontDescription01;
462   Vector<FontDescriptionRun> fontDescriptionRuns01;
463   Vector<FontId> expectedFontIds01;
464   Vector<bool> expectedIsFontDefault01;
465
466   TextAbstraction::FontDescription defaultFontDescription02;
467   Vector<FontDescriptionRun> fontDescriptionRuns02;
468   Vector<FontId> expectedFontIds02;
469   expectedFontIds02.PushBack( 0u );
470   expectedFontIds02.PushBack( 0u );
471   Vector<bool> expectedIsFontDefault02;
472   expectedIsFontDefault02.PushBack( true );
473   expectedIsFontDefault02.PushBack( true );
474
475   TextAbstraction::FontDescription defaultFontDescription03;
476   defaultFontDescription03.family = "DejaVu Serif";
477   Vector<FontDescriptionRun> fontDescriptionRuns03;
478
479   FontDescriptionRun fontDescription0301 =
480   {
481     {
482       0u,
483       2u
484     },
485     const_cast<char*>( "DejaVu Sans" ),
486     11u,
487     TextAbstraction::FontWeight::NONE,
488     TextAbstraction::FontWidth::NONE,
489     TextAbstraction::FontSlant::NONE,
490     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
491     true,
492     false,
493     false,
494     false,
495     false
496   };
497   FontDescriptionRun fontDescription0302 =
498   {
499     {
500       2u,
501       2u
502     },
503     NULL,
504     0u,
505     TextAbstraction::FontWeight::NONE,
506     TextAbstraction::FontWidth::NONE,
507     TextAbstraction::FontSlant::ITALIC,
508     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
509     false,
510     false,
511     false,
512     true,
513     false
514   };
515   FontDescriptionRun fontDescription0303 =
516   {
517     {
518       4u,
519       2u
520     },
521     NULL,
522     0u,
523     TextAbstraction::FontWeight::BOLD,
524     TextAbstraction::FontWidth::NONE,
525     TextAbstraction::FontSlant::NONE,
526     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
527     false,
528     true,
529     false,
530     false,
531     false
532   };
533   FontDescriptionRun fontDescription0304 =
534   {
535     {
536       6u,
537       2u
538     },
539     NULL,
540     0u,
541     TextAbstraction::FontWeight::NONE,
542     TextAbstraction::FontWidth::NONE,
543     TextAbstraction::FontSlant::NONE,
544     NON_DEFAULT_FONT_SIZE,
545     false,
546     false,
547     false,
548     false,
549     true
550   };
551   FontDescriptionRun fontDescription0305 =
552   {
553     {
554       8u,
555       2u
556     },
557     NULL,
558     0u,
559     TextAbstraction::FontWeight::NONE,
560     TextAbstraction::FontWidth::EXPANDED,
561     TextAbstraction::FontSlant::NONE,
562     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
563     false,
564     false,
565     true,
566     false,
567     false
568   };
569
570   fontDescriptionRuns03.PushBack( fontDescription0301 );
571   fontDescriptionRuns03.PushBack( fontDescription0302 );
572   fontDescriptionRuns03.PushBack( fontDescription0303 );
573   fontDescriptionRuns03.PushBack( fontDescription0304 );
574   fontDescriptionRuns03.PushBack( fontDescription0305 );
575
576   Vector<FontId> expectedFontIds03;
577   expectedFontIds03.PushBack( 1u );
578   expectedFontIds03.PushBack( 1u );
579   expectedFontIds03.PushBack( 5u );
580   expectedFontIds03.PushBack( 5u );
581   expectedFontIds03.PushBack( 4u );
582   expectedFontIds03.PushBack( 4u );
583   expectedFontIds03.PushBack( 3u );
584   expectedFontIds03.PushBack( 3u );
585   expectedFontIds03.PushBack( 6u );
586   expectedFontIds03.PushBack( 6u );
587   Vector<bool> expectedIsFontDefault03;
588   expectedIsFontDefault03.PushBack( false );
589   expectedIsFontDefault03.PushBack( false );
590   expectedIsFontDefault03.PushBack( false );
591   expectedIsFontDefault03.PushBack( false );
592   expectedIsFontDefault03.PushBack( false );
593   expectedIsFontDefault03.PushBack( false );
594   expectedIsFontDefault03.PushBack( false );
595   expectedIsFontDefault03.PushBack( false );
596   expectedIsFontDefault03.PushBack( false );
597   expectedIsFontDefault03.PushBack( false );
598
599   const MergeFontDescriptionsData data[] =
600   {
601     {
602       "void text.",
603       fontDescriptionRuns01,
604       defaultFontDescription01,
605       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
606       1.0f,
607       0u,
608       0u,
609       expectedFontIds01,
610       expectedIsFontDefault01
611     },
612     {
613       "No description runs.",
614       fontDescriptionRuns02,
615       defaultFontDescription02,
616       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
617       1.0f,
618       0u,
619       2u,
620       expectedFontIds02,
621       expectedIsFontDefault02
622     },
623     {
624       "Some description runs.",
625       fontDescriptionRuns03,
626       defaultFontDescription03,
627       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
628       1.0f,
629       0u,
630       10u,
631       expectedFontIds03,
632       expectedIsFontDefault03
633     }
634   };
635   const unsigned int numberOfTests = 3u;
636
637   for( unsigned int index = 0u; index < numberOfTests; ++index )
638   {
639     if( !MergeFontDescriptionsTest( data[index] ) )
640     {
641       tet_result(TET_FAIL);
642     }
643   }
644
645   tet_result(TET_PASS);
646   END_TEST;
647 }
648
649 int UtcDaliTextMultiLanguageConstructor(void)
650 {
651   ToolkitTestApplication application;
652   tet_infoline(" UtcDaliTextMultiLanguageConstructor");
653
654   MultilanguageSupport multilanguageSupport;
655   DALI_TEST_CHECK( !multilanguageSupport );
656
657   MultilanguageSupport multilanguageSupport1 = MultilanguageSupport::Get();
658   DALI_TEST_CHECK( multilanguageSupport1 );
659
660   // To increase coverage.
661   MultilanguageSupport multilanguageSupport2 = MultilanguageSupport::Get();
662   DALI_TEST_CHECK( multilanguageSupport2 );
663
664   DALI_TEST_CHECK( multilanguageSupport1 == multilanguageSupport2 );
665
666   tet_result(TET_PASS);
667   END_TEST;
668 }
669
670 int UtcDaliTextMultiLanguageSetScripts(void)
671 {
672   ToolkitTestApplication application;
673   tet_infoline(" UtcDaliTextMultiLanguageSetScripts" );
674
675   // Void text.
676   Vector<ScriptRun> scriptRuns00;
677
678   // Hello world.
679   Vector<ScriptRun> scriptRuns01;
680   ScriptRun scriptRun0100 =
681   {
682     {
683       0u,
684       11u,
685     },
686     TextAbstraction::LATIN
687   };
688   scriptRuns01.PushBack( scriptRun0100 );
689
690   // Mix of LTR '\n'and RTL
691   Vector<ScriptRun> scriptRuns02;
692   ScriptRun scriptRun0200 =
693   {
694     {
695       0u,
696       12u,
697     },
698     TextAbstraction::LATIN
699   };
700   ScriptRun scriptRun0201 =
701   {
702     {
703       12u,
704       13u,
705     },
706     TextAbstraction::ARABIC
707   };
708   scriptRuns02.PushBack( scriptRun0200 );
709   scriptRuns02.PushBack( scriptRun0201 );
710
711   // Mix of RTL '\n'and LTR
712   Vector<ScriptRun> scriptRuns03;
713   ScriptRun scriptRun0300 =
714   {
715     {
716       0u,
717       14u,
718     },
719     TextAbstraction::ARABIC
720   };
721   ScriptRun scriptRun0301 =
722   {
723     {
724       14u,
725       11u,
726     },
727     TextAbstraction::LATIN
728   };
729   scriptRuns03.PushBack( scriptRun0300 );
730   scriptRuns03.PushBack( scriptRun0301 );
731
732   // White spaces. At the beginning of the text.
733   Vector<ScriptRun> scriptRuns04;
734   ScriptRun scriptRun0400 =
735   {
736     {
737       0u,
738       15u,
739     },
740     TextAbstraction::LATIN
741   };
742   scriptRuns04.PushBack( scriptRun0400 );
743
744   // White spaces. At the end of the text.
745   Vector<ScriptRun> scriptRuns05;
746   ScriptRun scriptRun0500 =
747   {
748     {
749       0u,
750       15u,
751     },
752     TextAbstraction::LATIN
753   };
754   scriptRuns05.PushBack( scriptRun0500 );
755
756   // White spaces. At the middle of the text.
757   Vector<ScriptRun> scriptRuns06;
758   ScriptRun scriptRun0600 =
759   {
760     {
761       0u,
762       15u,
763     },
764     TextAbstraction::LATIN
765   };
766   scriptRuns06.PushBack( scriptRun0600 );
767
768   // White spaces between different scripts.
769   Vector<ScriptRun> scriptRuns07;
770   ScriptRun scriptRun0700 =
771   {
772     {
773       0u,
774       8u,
775     },
776     TextAbstraction::LATIN
777   };
778   ScriptRun scriptRun0701 =
779   {
780     {
781       8u,
782       5u,
783     },
784     TextAbstraction::HANGUL
785   };
786   scriptRuns07.PushBack( scriptRun0700 );
787   scriptRuns07.PushBack( scriptRun0701 );
788
789   // White spaces between different scripts and differetn directions. Starting LTR.
790   Vector<ScriptRun> scriptRuns08;
791   ScriptRun scriptRun0800 =
792   {
793     {
794       0u,
795       18u,
796     },
797     TextAbstraction::LATIN
798   };
799   ScriptRun scriptRun0801 =
800   {
801     {
802       18u,
803       14u,
804     },
805     TextAbstraction::ARABIC
806   };
807   ScriptRun scriptRun0802 =
808   {
809     {
810       32u,
811       18u,
812     },
813     TextAbstraction::HANGUL
814   };
815   scriptRuns08.PushBack( scriptRun0800 );
816   scriptRuns08.PushBack( scriptRun0801 );
817   scriptRuns08.PushBack( scriptRun0802 );
818
819   // White spaces between different scripts and differetn directions. Starting RTL.
820   Vector<ScriptRun> scriptRuns09;
821   ScriptRun scriptRun0900 =
822   {
823     {
824       0u,
825       21u,
826     },
827     TextAbstraction::ARABIC
828   };
829   ScriptRun scriptRun0901 =
830   {
831     {
832       21u,
833       16u,
834     },
835     TextAbstraction::LATIN
836   };
837   ScriptRun scriptRun0902 =
838   {
839     {
840       37u,
841       10u,
842     },
843     TextAbstraction::HANGUL
844   };
845   ScriptRun scriptRun0903 =
846   {
847     {
848       47u,
849       20u,
850     },
851     TextAbstraction::ARABIC
852   };
853   scriptRuns09.PushBack( scriptRun0900 );
854   scriptRuns09.PushBack( scriptRun0901 );
855   scriptRuns09.PushBack( scriptRun0902 );
856   scriptRuns09.PushBack( scriptRun0903 );
857
858   // Paragraphs with different directions.
859   Vector<ScriptRun> scriptRuns10;
860   ScriptRun scriptRun1000 =
861   {
862     {
863       0u,
864       20u,
865     },
866     TextAbstraction::ARABIC
867   };
868   ScriptRun scriptRun1001 =
869   {
870     {
871       20u,
872       12u,
873     },
874     TextAbstraction::HEBREW
875   };
876   ScriptRun scriptRun1002 =
877   {
878     {
879       32u,
880       17u,
881     },
882     TextAbstraction::ARABIC
883   };
884   ScriptRun scriptRun1003 =
885   {
886     {
887       49u,
888       18u,
889     },
890     TextAbstraction::LATIN
891   };
892   ScriptRun scriptRun1004 =
893   {
894     {
895       67u,
896       14u,
897     },
898     TextAbstraction::HANGUL
899   };
900   ScriptRun scriptRun1005 =
901   {
902     {
903       81u,
904       19u,
905     },
906     TextAbstraction::ARABIC
907   };
908   ScriptRun scriptRun1006 =
909   {
910     {
911       100u,
912       13u,
913     },
914     TextAbstraction::LATIN
915   };
916   ScriptRun scriptRun1007 =
917   {
918     {
919       113u,
920       16u,
921     },
922     TextAbstraction::HEBREW
923   };
924   ScriptRun scriptRun1008 =
925   {
926     {
927       129u,
928       20u,
929     },
930     TextAbstraction::LATIN
931   };
932   ScriptRun scriptRun1009 =
933   {
934     {
935       149u,
936       14u,
937     },
938     TextAbstraction::ARABIC
939   };
940   ScriptRun scriptRun1010 =
941   {
942     {
943       163u,
944       18u,
945     },
946     TextAbstraction::HANGUL
947   };
948   ScriptRun scriptRun1011 =
949   {
950     {
951       181u,
952       17u,
953     },
954     TextAbstraction::HANGUL
955   };
956   scriptRuns10.PushBack( scriptRun1000 );
957   scriptRuns10.PushBack( scriptRun1001 );
958   scriptRuns10.PushBack( scriptRun1002 );
959   scriptRuns10.PushBack( scriptRun1003 );
960   scriptRuns10.PushBack( scriptRun1004 );
961   scriptRuns10.PushBack( scriptRun1005 );
962   scriptRuns10.PushBack( scriptRun1006 );
963   scriptRuns10.PushBack( scriptRun1007 );
964   scriptRuns10.PushBack( scriptRun1008 );
965   scriptRuns10.PushBack( scriptRun1009 );
966   scriptRuns10.PushBack( scriptRun1010 );
967   scriptRuns10.PushBack( scriptRun1011 );
968
969   // Paragraphs with no scripts mixed with paragraphs with scripts.
970   Vector<ScriptRun> scriptRuns11;
971   ScriptRun scriptRun1100 =
972   {
973     {
974       0u,
975       3u,
976     },
977     TextAbstraction::UNKNOWN
978   };
979   ScriptRun scriptRun1101 =
980   {
981     {
982       3u,
983       3u,
984     },
985     TextAbstraction::UNKNOWN
986   };
987   ScriptRun scriptRun1102 =
988   {
989     {
990       6u,
991       19u,
992     },
993     TextAbstraction::LATIN
994   };
995   ScriptRun scriptRun1103 =
996   {
997     {
998       25u,
999       3u,
1000     },
1001     TextAbstraction::UNKNOWN
1002   };
1003   ScriptRun scriptRun1104 =
1004   {
1005     {
1006       28u,
1007       3u,
1008     },
1009     TextAbstraction::UNKNOWN
1010   };
1011   ScriptRun scriptRun1105 =
1012   {
1013     {
1014       31u,
1015       15u,
1016     },
1017     TextAbstraction::HEBREW
1018   };
1019   ScriptRun scriptRun1106 =
1020   {
1021     {
1022       46u,
1023       2u,
1024     },
1025     TextAbstraction::UNKNOWN
1026   };
1027   ScriptRun scriptRun1107 =
1028   {
1029     {
1030       48u,
1031       2u,
1032     },
1033     TextAbstraction::UNKNOWN
1034   };
1035   ScriptRun scriptRun1108 =
1036   {
1037     {
1038       50u,
1039       2u,
1040     },
1041     TextAbstraction::UNKNOWN
1042   };
1043   scriptRuns11.PushBack( scriptRun1100 );
1044   scriptRuns11.PushBack( scriptRun1101 );
1045   scriptRuns11.PushBack( scriptRun1102 );
1046   scriptRuns11.PushBack( scriptRun1103 );
1047   scriptRuns11.PushBack( scriptRun1104 );
1048   scriptRuns11.PushBack( scriptRun1105 );
1049   scriptRuns11.PushBack( scriptRun1106 );
1050   scriptRuns11.PushBack( scriptRun1107 );
1051   scriptRuns11.PushBack( scriptRun1108 );
1052
1053   // Paragraphs with no scripts.
1054   Vector<ScriptRun> scriptRuns12;
1055   ScriptRun scriptRun1200 =
1056   {
1057     {
1058       0u,
1059       3u,
1060     },
1061     TextAbstraction::UNKNOWN
1062   };
1063   ScriptRun scriptRun1201 =
1064   {
1065     {
1066       3u,
1067       3u,
1068     },
1069     TextAbstraction::UNKNOWN
1070   };
1071   ScriptRun scriptRun1202 =
1072   {
1073     {
1074       6u,
1075       3u,
1076     },
1077     TextAbstraction::UNKNOWN
1078   };
1079   ScriptRun scriptRun1203 =
1080   {
1081     {
1082       9u,
1083       2u,
1084     },
1085     TextAbstraction::UNKNOWN
1086   };
1087   scriptRuns12.PushBack( scriptRun1200 );
1088   scriptRuns12.PushBack( scriptRun1201 );
1089   scriptRuns12.PushBack( scriptRun1202 );
1090   scriptRuns12.PushBack( scriptRun1203 );
1091
1092   Vector<ScriptRun> scriptRuns13;
1093   ScriptRun scriptRun1301 =
1094   {
1095     {
1096       0u,
1097       4u,
1098     },
1099     TextAbstraction::UNKNOWN
1100   };
1101   scriptRuns13.PushBack( scriptRun1301 );
1102
1103   const ScriptsData data[] =
1104   {
1105     {
1106       "void text",
1107       "",
1108       0u,
1109       0u,
1110       scriptRuns00,
1111     },
1112     {
1113       "Easy latin script",
1114       "Hello world",
1115       0u,
1116       11u,
1117       scriptRuns01,
1118     },
1119     {
1120       "Mix of LTR '\\n'and RTL",
1121       "Hello world\nمرحبا بالعالم",
1122       0u,
1123       25u,
1124       scriptRuns02,
1125     },
1126     {
1127       "Update mix of LTR '\\n'and RTL. Update LTR",
1128       "Hello world\nمرحبا بالعالم",
1129       0u,
1130       12u,
1131       scriptRuns02,
1132     },
1133     {
1134       "Update mix of LTR '\\n'and RTL. Update RTL",
1135       "Hello world\nمرحبا بالعالم",
1136       12u,
1137       13u,
1138       scriptRuns02,
1139     },
1140     {
1141       "Mix of RTL '\\n'and LTR",
1142       "مرحبا بالعالم\nHello world",
1143       0u,
1144       25u,
1145       scriptRuns03,
1146     },
1147     {
1148       "Update mix of RTL '\\n'and LTR. Update RTL",
1149       "مرحبا بالعالم\nHello world",
1150       0u,
1151       14u,
1152       scriptRuns03,
1153     },
1154     {
1155       "Update mix of RTL '\\n'and LTR. Update LTR",
1156       "مرحبا بالعالم\nHello world",
1157       14u,
1158       11u,
1159       scriptRuns03,
1160     },
1161     {
1162       "White spaces. At the beginning of the text.",
1163       "    Hello world",
1164       0u,
1165       15u,
1166       scriptRuns04,
1167     },
1168     {
1169       "White spaces. At the end of the text.",
1170       "Hello world    ",
1171       0u,
1172       15u,
1173       scriptRuns05,
1174     },
1175     {
1176       "White spaces. At the middle of the text.",
1177       "Hello     world",
1178       0u,
1179       15u,
1180       scriptRuns06,
1181     },
1182     {
1183       "White spaces between different scripts.",
1184       "  Hel   세계   ",
1185       0u,
1186       13u,
1187       scriptRuns07,
1188     },
1189     {
1190       "White spaces between different scripts and differetn directions. Starting LTR.",
1191       "  Hello   world   مرحبا  بالعالم     안녕하세요   세계   ",
1192       0u,
1193       50u,
1194       scriptRuns08,
1195     },
1196     {
1197       "White spaces between different scripts and differetn directions. Starting RTL.",
1198       "   مرحبا  بالعالم    Hello   world   안녕하세요   세계   مرحبا  بالعالم   ",
1199       0u,
1200       67u,
1201       scriptRuns09
1202     },
1203     {
1204       "Paragraphs with different directions.",
1205       "   مرحبا  بالعالم   שלום עולם   مرحبا  بالعالم  \n "
1206       " Hello   world   안녕하세요   세계   \n "
1207       "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
1208       " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
1209       "   안녕하세요   세계   ",
1210       0u,
1211       198u,
1212       scriptRuns10
1213     },
1214     {
1215       "Update paragraphs with different directions. Update initial paragraphs.",
1216       "   مرحبا  بالعالم   שלום עולם   مرحبا  بالعالم  \n "
1217       " Hello   world   안녕하세요   세계   \n "
1218       "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
1219       " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
1220       "   안녕하세요   세계   ",
1221       0u,
1222       81u,
1223       scriptRuns10
1224     },
1225     {
1226       "Update paragraphs with different directions. Update middle paragraphs.",
1227       "   مرحبا  بالعالم   שלום עולם   مرحبا  بالعالم  \n "
1228       " Hello   world   안녕하세요   세계   \n "
1229       "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
1230       " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
1231       "   안녕하세요   세계   ",
1232       49u,
1233       80u,
1234       scriptRuns10
1235     },
1236     {
1237       "Update paragraphs with different directions. Update final paragraphs.",
1238       "   مرحبا  بالعالم   שלום עולם   مرحبا  بالعالم  \n "
1239       " Hello   world   안녕하세요   세계   \n "
1240       "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
1241       " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
1242       "   안녕하세요   세계   ",
1243       129u,
1244       69u,
1245       scriptRuns10
1246     },
1247     {
1248       "Paragraphs with no scripts mixed with paragraphs with scripts.",
1249       "  \n  \n   Hello   world  \n  \n  \n   שלום עולם  \n \n \n  ",
1250       0u,
1251       52u,
1252       scriptRuns11
1253     },
1254     {
1255       "Paragraphs with no scripts.",
1256       "  \n  \n  \n  ",
1257       0u,
1258       11u,
1259       scriptRuns12
1260     },
1261     {
1262       "Update paragraphs with no scripts. Update initial paragraphs.",
1263       "  \n  \n  \n  ",
1264       0u,
1265       3u,
1266       scriptRuns12
1267     },
1268     {
1269       "Update paragraphs with no scripts. Update middle paragraphs.",
1270       "  \n  \n  \n  ",
1271       3u,
1272       6u,
1273       scriptRuns12
1274     },
1275     {
1276       "Update paragraphs with no scripts. Update final paragraphs.",
1277       "  \n  \n  \n  ",
1278       9u,
1279       2u,
1280       scriptRuns12
1281     },
1282     {
1283       "Unknown scripts.",
1284       "ᚩᚯᚱᚸ", // Runic script not currentlu supported.
1285       0u,
1286       4u,
1287       scriptRuns13
1288     }
1289   };
1290   const unsigned int numberOfTests = 24u;
1291
1292   for( unsigned int index = 0u; index < numberOfTests; ++index )
1293   {
1294     if( !ScriptsTest( data[index] ) )
1295     {
1296       tet_result(TET_FAIL);
1297     }
1298   }
1299
1300   tet_result(TET_PASS);
1301   END_TEST;
1302 }
1303
1304 int UtcDaliTextMultiLanguageValidateFonts01(void)
1305 {
1306   ToolkitTestApplication application;
1307   tet_infoline(" UtcDaliTextMultiLanguageValidateFonts");
1308
1309   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
1310
1311   char* pathNamePtr = get_current_dir_name();
1312   const std::string pathName( pathNamePtr );
1313   free( pathNamePtr );
1314
1315   const PointSize26Dot6 pointSize01 = static_cast<PointSize26Dot6>( 21.f * 64.f );
1316   const PointSize26Dot6 pointSize02 = static_cast<PointSize26Dot6>( 35.f * 64.f );
1317
1318   // Load some fonts.
1319   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
1320   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" );
1321   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/BreezeColorEmoji.ttf", EMOJI_FONT_SIZE );
1322   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf", pointSize01 );
1323   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf", pointSize02 );
1324   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf", pointSize01 );
1325   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf", pointSize02 );
1326
1327   // Font id 1 --> TizenSansArabicRegular.ttf
1328   // Font id 2 --> TizenSansHebrewRegular.ttf
1329   // Font id 3 --> BreezeColorEmoji.ttf
1330   // Font id 4 --> TizenSansRegular.ttf, size 8
1331   // Font id 5 --> TizenSansRegular.ttf, size 16
1332   // Font id 6 --> TizenSansHebrewRegular.ttf, size 8
1333   // Font id 7 --> TizenSansHebrewRegular.ttf, size 16
1334   // Font id 8 --> (default)
1335
1336   Vector<FontRun> fontRuns01;
1337   Vector<FontDescriptionRun> fontDescriptions01;
1338
1339   FontRun fontRun0201 =
1340   {
1341     {
1342       0u,
1343       11u
1344     },
1345     8u
1346   };
1347   Vector<FontRun> fontRuns02;
1348   fontRuns02.PushBack( fontRun0201 );
1349
1350   FontDescriptionRun fontDescription0201 =
1351   {
1352     {
1353       0u,
1354       11u
1355     },
1356     const_cast<char*>( "TizenSans" ),
1357     9u,
1358     TextAbstraction::FontWeight::NORMAL,
1359     TextAbstraction::FontWidth::NORMAL,
1360     TextAbstraction::FontSlant::NORMAL,
1361     0u,
1362     true,
1363     false,
1364     false,
1365     false,
1366     false
1367   };
1368   Vector<FontDescriptionRun> fontDescriptions02;
1369   fontDescriptions02.PushBack( fontDescription0201 );
1370
1371   FontRun fontRun0301 =
1372   {
1373     {
1374       0u,
1375       12u
1376     },
1377     8u
1378   };
1379   FontRun fontRun0302 =
1380   {
1381     {
1382       12u,
1383       12u
1384     },
1385     8u
1386   };
1387   FontRun fontRun0303 =
1388   {
1389     {
1390       24u,
1391       4u
1392     },
1393     8u
1394   };
1395   Vector<FontRun> fontRuns03;
1396   fontRuns03.PushBack( fontRun0301 );
1397   fontRuns03.PushBack( fontRun0302 );
1398   fontRuns03.PushBack( fontRun0303 );
1399
1400   Vector<FontDescriptionRun> fontDescriptions03;
1401
1402   FontRun fontRun0701 =
1403   {
1404     {
1405       0u,
1406       4u
1407     },
1408     2u
1409   };
1410   FontRun fontRun0702 =
1411   {
1412     {
1413       4u,
1414       1u
1415     },
1416     8u
1417   };
1418   FontRun fontRun0703 =
1419   {
1420     {
1421       5u,
1422       4u
1423     },
1424     2u
1425   };
1426   Vector<FontRun> fontRuns07;
1427   fontRuns07.PushBack( fontRun0701 );
1428   fontRuns07.PushBack( fontRun0702 );
1429   fontRuns07.PushBack( fontRun0703 );
1430
1431   FontDescriptionRun fontDescription0701 =
1432   {
1433     {
1434       0u,
1435       4u
1436     },
1437     const_cast<char*>( "TizenSansHebrew" ),
1438     15u,
1439     TextAbstraction::FontWeight::NORMAL,
1440     TextAbstraction::FontWidth::NORMAL,
1441     TextAbstraction::FontSlant::NORMAL,
1442     0u,
1443     true,
1444     false,
1445     false,
1446     false,
1447     false
1448   };
1449   FontDescriptionRun fontDescription0702 =
1450   {
1451     {
1452       5u,
1453       4u
1454     },
1455     const_cast<char*>( "TizenSansHebrew" ),
1456     15u,
1457     TextAbstraction::FontWeight::NORMAL,
1458     TextAbstraction::FontWidth::NORMAL,
1459     TextAbstraction::FontSlant::NORMAL,
1460     0u,
1461     true,
1462     false,
1463     false,
1464     false,
1465     false
1466   };
1467   Vector<FontDescriptionRun> fontDescriptions07;
1468   fontDescriptions07.PushBack( fontDescription0701 );
1469   fontDescriptions07.PushBack( fontDescription0702 );
1470
1471   FontRun fontRun0801 =
1472   {
1473     {
1474       0u,
1475       9u
1476     },
1477     2u
1478   };
1479   Vector<FontRun> fontRuns08;
1480   fontRuns08.PushBack( fontRun0801 );
1481
1482   Vector<FontDescriptionRun> fontDescriptions08;
1483
1484   FontRun fontRun0901 =
1485   {
1486     {
1487       0u,
1488       4u
1489     },
1490     3u
1491   };
1492   Vector<FontRun> fontRuns09;
1493   fontRuns09.PushBack( fontRun0901 );
1494
1495   Vector<FontDescriptionRun> fontDescriptions09;
1496   FontDescriptionRun fontDescription0901 =
1497   {
1498     {
1499       0u,
1500       4u
1501     },
1502     const_cast<char*>( "BreezeColorEmoji" ),
1503     16u,
1504     TextAbstraction::FontWeight::NORMAL,
1505     TextAbstraction::FontWidth::NORMAL,
1506     TextAbstraction::FontSlant::NORMAL,
1507     EMOJI_FONT_SIZE,
1508     true,
1509     false,
1510     false,
1511     false,
1512     true
1513   };
1514   fontDescriptions09.PushBack( fontDescription0901 );
1515
1516   FontRun fontRun1001 =
1517   {
1518     {
1519       0u,
1520       13u
1521     },
1522     4u
1523   };
1524   FontRun fontRun1002 =
1525   {
1526     {
1527       13u,
1528       9u
1529     },
1530     6u
1531   };
1532   FontRun fontRun1003 =
1533   {
1534     {
1535       22u,
1536       15u
1537     },
1538     5u
1539   };
1540   FontRun fontRun1004 =
1541   {
1542     {
1543       37u,
1544       9u
1545     },
1546     7u
1547   };
1548   Vector<FontRun> fontRuns10;
1549   fontRuns10.PushBack( fontRun1001 );
1550   fontRuns10.PushBack( fontRun1002 );
1551   fontRuns10.PushBack( fontRun1003 );
1552   fontRuns10.PushBack( fontRun1004 );
1553
1554   FontDescriptionRun fontDescription1001 =
1555   {
1556     {
1557       0u,
1558       13u
1559     },
1560     const_cast<char*>( "TizenSans" ),
1561     9u,
1562     TextAbstraction::FontWeight::NORMAL,
1563     TextAbstraction::FontWidth::NORMAL,
1564     TextAbstraction::FontSlant::NORMAL,
1565     pointSize01,
1566     true,
1567     false,
1568     false,
1569     false,
1570     true
1571   };
1572   FontDescriptionRun fontDescription1002 =
1573   {
1574     {
1575       13u,
1576       9u
1577     },
1578     const_cast<char*>( "TizenSansHebrew" ),
1579     15u,
1580     TextAbstraction::FontWeight::NORMAL,
1581     TextAbstraction::FontWidth::NORMAL,
1582     TextAbstraction::FontSlant::NORMAL,
1583     pointSize01,
1584     true,
1585     false,
1586     false,
1587     false,
1588     true
1589   };
1590   FontDescriptionRun fontDescription1003 =
1591   {
1592     {
1593       22u,
1594       15u
1595     },
1596     const_cast<char*>( "TizenSans" ),
1597     9u,
1598     TextAbstraction::FontWeight::NORMAL,
1599     TextAbstraction::FontWidth::NORMAL,
1600     TextAbstraction::FontSlant::NORMAL,
1601     pointSize02,
1602     true,
1603     false,
1604     false,
1605     false,
1606     true
1607   };
1608   FontDescriptionRun fontDescription1004 =
1609   {
1610     {
1611       37u,
1612       9u
1613     },
1614     const_cast<char*>( "TizenSansHebrew" ),
1615     15u,
1616     TextAbstraction::FontWeight::NORMAL,
1617     TextAbstraction::FontWidth::NORMAL,
1618     TextAbstraction::FontSlant::NORMAL,
1619     pointSize02,
1620     true,
1621     false,
1622     false,
1623     false,
1624     true
1625   };
1626   Vector<FontDescriptionRun> fontDescriptions10;
1627   fontDescriptions10.PushBack( fontDescription1001 );
1628   fontDescriptions10.PushBack( fontDescription1002 );
1629   fontDescriptions10.PushBack( fontDescription1003 );
1630   fontDescriptions10.PushBack( fontDescription1004 );
1631
1632   FontRun fontRun1101 =
1633   {
1634     {
1635       0u,
1636       22u
1637     },
1638     5u
1639   };
1640   Vector<FontRun> fontRuns11;
1641   fontRuns11.PushBack( fontRun1101 );
1642
1643   FontDescriptionRun fontDescription1101 =
1644   {
1645     {
1646       0,
1647       22u
1648     },
1649     const_cast<char*>( "TizenSans" ),
1650     9u,
1651     TextAbstraction::FontWeight::NORMAL,
1652     TextAbstraction::FontWidth::NORMAL,
1653     TextAbstraction::FontSlant::NORMAL,
1654     pointSize02,
1655     true,
1656     false,
1657     false,
1658     false,
1659     true
1660   };
1661   Vector<FontDescriptionRun> fontDescriptions11;
1662   fontDescriptions11.PushBack( fontDescription1101 );
1663
1664   FontRun fontRun1201 =
1665   {
1666     {
1667       0u,
1668       6u
1669     },
1670     8u
1671   };
1672   FontRun fontRun1202 =
1673   {
1674     {
1675       6u,
1676       1u
1677     },
1678     9u
1679   };
1680   FontRun fontRun1203 =
1681   {
1682     {
1683       7u,
1684       5u
1685     },
1686     8u
1687   };
1688   Vector<FontRun> fontRuns12;
1689   fontRuns12.PushBack( fontRun1201 );
1690   fontRuns12.PushBack( fontRun1202 );
1691   fontRuns12.PushBack( fontRun1203 );
1692
1693   FontDescriptionRun fontDescription1201 =
1694   {
1695     {
1696       0u,
1697       6u
1698     },
1699     const_cast<char*>( "TizenSans" ),
1700     9u,
1701     TextAbstraction::FontWeight::NORMAL,
1702     TextAbstraction::FontWidth::NORMAL,
1703     TextAbstraction::FontSlant::NORMAL,
1704     0u,
1705     true,
1706     false,
1707     false,
1708     false,
1709     false
1710   };
1711   FontDescriptionRun fontDescription1202 =
1712   {
1713     {
1714       6u,
1715       1u
1716     },
1717     const_cast<char*>( "TizenSans" ),
1718     9u,
1719     TextAbstraction::FontWeight::NORMAL,
1720     TextAbstraction::FontWidth::NORMAL,
1721     TextAbstraction::FontSlant::NORMAL,
1722     0u,
1723     true,
1724     false,
1725     false,
1726     false,
1727     false
1728   };
1729   FontDescriptionRun fontDescription1203 =
1730   {
1731     {
1732       7u,
1733       5u
1734     },
1735     const_cast<char*>( "TizenSans" ),
1736     9u,
1737     TextAbstraction::FontWeight::NORMAL,
1738     TextAbstraction::FontWidth::NORMAL,
1739     TextAbstraction::FontSlant::NORMAL,
1740     0u,
1741     true,
1742     false,
1743     false,
1744     false,
1745     false
1746   };
1747   Vector<FontDescriptionRun> fontDescriptions12;
1748   fontDescriptions12.PushBack( fontDescription1201 );
1749   fontDescriptions12.PushBack( fontDescription1202 );
1750   fontDescriptions12.PushBack( fontDescription1203 );
1751
1752   const ValidateFontsData data[] =
1753   {
1754     {
1755       "void text.",
1756       "",
1757       "/tizen/TizenSansRegular.ttf",
1758       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1759       1.0f,
1760       0u,
1761       0u,
1762       fontDescriptions01,
1763       fontRuns01
1764     },
1765     {
1766       "Easy latin script.",
1767       "Hello world",
1768       "/tizen/TizenSansRegular.ttf",
1769       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1770       1.0f,
1771       0u,
1772       11u,
1773       fontDescriptions02,
1774       fontRuns02
1775     },
1776     {
1777       "Different paragraphs.",
1778       "Hello world\nhello world\ndemo",
1779       "/tizen/TizenSansRegular.ttf",
1780       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1781       1.0f,
1782       0u,
1783       28u,
1784       fontDescriptions03,
1785       fontRuns03
1786     },
1787     {
1788       "Different paragraphs. Update the initial paragraph.",
1789       "Hello world\nhello world\ndemo",
1790       "/tizen/TizenSansRegular.ttf",
1791       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1792       1.0f,
1793       0u,
1794       12u,
1795       fontDescriptions03,
1796       fontRuns03
1797     },
1798     {
1799       "Different paragraphs. Update the middle paragraph.",
1800       "Hello world\nhello world\ndemo",
1801       "/tizen/TizenSansRegular.ttf",
1802       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1803       1.0f,
1804       12u,
1805       12u,
1806       fontDescriptions03,
1807       fontRuns03
1808     },
1809     {
1810       "Different paragraphs. Update the final paragraph.",
1811       "Hello world\nhello world\ndemo",
1812       "/tizen/TizenSansRegular.ttf",
1813       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1814       1.0f,
1815       24u,
1816       4u,
1817       fontDescriptions03,
1818       fontRuns03
1819     },
1820     {
1821       "Hebrew text. Default font: latin",
1822       "שלום עולם",
1823       "/tizen/TizenSansRegular.ttf",
1824       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1825       1.0f,
1826       0u,
1827       9u,
1828       fontDescriptions07,
1829       fontRuns07
1830     },
1831     {
1832       "Hebrew text. Default font: hebrew",
1833       "שלום עולם",
1834       "/tizen/TizenSansHebrewRegular.ttf",
1835       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1836       1.0f,
1837       0u,
1838       9u,
1839       fontDescriptions08,
1840       fontRuns08
1841     },
1842     {
1843       "Emojis",
1844       "\xF0\x9F\x98\x81\xF0\x9F\x98\x82\xF0\x9F\x98\x83\xF0\x9F\x98\x84",
1845       "/tizen/BreezeColorEmoji.ttf",
1846       EMOJI_FONT_SIZE,
1847       1.0f,
1848       0u,
1849       4u,
1850       fontDescriptions09,
1851       fontRuns09
1852     },
1853     {
1854       "Mix text. Default font: latin. Different font sizes",
1855       "Hello world, שלום עולם, hello world, שלום עולם",
1856       "/tizen/TizenSansRegular.ttf",
1857       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1858       1.0f,
1859       0u,
1860       46u,
1861       fontDescriptions10,
1862       fontRuns10
1863     },
1864     {
1865       "Unknown script -> changed to LATIN",
1866       "WRC – The Official App",
1867       "/tizen/TizenSansRegular.ttf",
1868       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1869       1.0f,
1870       0u,
1871       22u,
1872       fontDescriptions11,
1873       fontRuns11
1874     },
1875     {
1876       "Common script.",
1877       "Hello \tworld",
1878       "/tizen/TizenSansRegular.ttf",
1879       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1880       1.0f,
1881       0u,
1882       12u,
1883       fontDescriptions12,
1884       fontRuns12
1885     },
1886   };
1887   const unsigned int numberOfTests = 12u;
1888
1889   for( unsigned int index = 0u; index < numberOfTests; ++index )
1890   {
1891     if( !ValidateFontTest( data[index] ) )
1892     {
1893       tet_result(TET_FAIL);
1894     }
1895   }
1896
1897   tet_result(TET_PASS);
1898   END_TEST;
1899 }
1900
1901 int UtcDaliTextMultiLanguageValidateFontsPerScriptCache(void)
1902 {
1903   ToolkitTestApplication application;
1904   tet_infoline(" UtcDaliTextMultiLanguageValidateFontsPerScriptCache");
1905
1906   std::size_t MAX_VALIDATE_FONTS_PER_SCRIPT_CACHE_SIZE = 63u;
1907   std::size_t VALIDATE_FONTS_PER_SCRIPT_REMAIN_COUNT   = 8u;
1908
1909   Dali::Toolkit::Text::Internal::ValidateFontsPerScript* validateFontsPerScript = new Dali::Toolkit::Text::Internal::ValidateFontsPerScript();
1910
1911   for(std::size_t i = 0u; i < MAX_VALIDATE_FONTS_PER_SCRIPT_CACHE_SIZE; i ++)
1912   {
1913     FontId fontId = i;
1914     validateFontsPerScript->Cache(fontId);
1915   }
1916
1917   DALI_TEST_EQUALS(MAX_VALIDATE_FONTS_PER_SCRIPT_CACHE_SIZE, validateFontsPerScript->mValidFonts.Count(), TEST_LOCATION);
1918
1919   FontId fontId = MAX_VALIDATE_FONTS_PER_SCRIPT_CACHE_SIZE;
1920   validateFontsPerScript->Cache(fontId);
1921
1922   DALI_TEST_EQUALS(VALIDATE_FONTS_PER_SCRIPT_REMAIN_COUNT, validateFontsPerScript->mValidFonts.Count(), TEST_LOCATION);
1923
1924   END_TEST;
1925 }
1926
1927 int UtcDaliTextMultiLanguageDefaultFontsCache(void)
1928 {
1929   ToolkitTestApplication application;
1930   tet_infoline(" UtcDaliTextMultiLanguageDefaultFontsCache");
1931
1932   std::size_t MAX_DEFAULT_FONTS_CACHE_SIZE = 15;
1933   std::size_t DEFAULT_FONTS_REMAIN_COUNT   = 2;
1934
1935   Dali::Toolkit::Text::Internal::DefaultFonts* defaultFontsPerScript = new Dali::Toolkit::Text::Internal::DefaultFonts();
1936
1937   for(std::size_t i = 0u; i < MAX_DEFAULT_FONTS_CACHE_SIZE; i ++)
1938   {
1939     TextAbstraction::FontDescription fontDescription;
1940     FontId fontId = i;
1941     defaultFontsPerScript->Cache(fontDescription, fontId);
1942   }
1943
1944   DALI_TEST_EQUALS(MAX_DEFAULT_FONTS_CACHE_SIZE, defaultFontsPerScript->mFonts.size(), TEST_LOCATION);
1945
1946   TextAbstraction::FontDescription fontDescription;
1947   FontId fontId = MAX_DEFAULT_FONTS_CACHE_SIZE;
1948   defaultFontsPerScript->Cache(fontDescription, fontId);
1949
1950   DALI_TEST_EQUALS(DEFAULT_FONTS_REMAIN_COUNT, defaultFontsPerScript->mFonts.size(), TEST_LOCATION);
1951
1952   END_TEST;
1953 }
1954
1955 int UtcDaliTextMultiLanguageLocaleChange(void)
1956 {
1957   ToolkitTestApplication application;
1958   tet_infoline(" UtcDaliTextMultiLanguageLocaleChange");
1959
1960   Adaptor &adaptor = application.GetAdaptor();
1961   MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
1962
1963   std::string newLocale = "multi_TEST";
1964   adaptor.LocaleChangedSignal().Emit(newLocale);
1965
1966   application.SendNotification();
1967   application.Render();
1968
1969   DALI_TEST_EQUALS(newLocale.data(), GetImplementation(multilanguageSupport).GetLocale(), TEST_LOCATION);
1970
1971   END_TEST;
1972 }