7fc8f71fd37070bf2712e51b28c471b61504ca17
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-Text-MultiLanguage.cpp
1 /*
2  * Copyright (c) 2015 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/segmentation.h>
28 #include <dali-toolkit/internal/text/text-run-container.h>
29 #include <dali-toolkit-test-suite-utils.h>
30 #include <dali-toolkit/dali-toolkit.h>
31
32 using namespace Dali;
33 using namespace Toolkit;
34 using namespace Text;
35
36 // Tests the following functions with different scripts.
37 //
38 // void MergeFontDescriptions( const Vector<FontDescriptionRun>& fontDescriptions,
39 //                             Vector<FontId>& fontIds,
40 //                             const TextAbstraction::FontDescription& defaultFontDescription,
41 //                             TextAbstraction::PointSize26Dot6 defaultPointSize,
42 //                             CharacterIndex startIndex,
43 //                             Length numberOfCharacters );
44 //
45 // Script GetScript( Length index,
46 //                   Vector<ScriptRun>::ConstIterator& scriptRunIt,
47 //                   const Vector<ScriptRun>::ConstIterator& scriptRunEndIt );
48 //
49 // Constructor, destructor and MultilanguageSupport::Get()
50 //
51 // void MultilanguageSupport::SetScripts( const Vector<Character>& text,
52 //                                        CharacterIndex startIndex,
53 //                                        Length numberOfCharacters,
54 //                                        Vector<ScriptRun>& scripts );
55 //
56 // void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
57 //                                           const Vector<ScriptRun>& scripts,
58 //                                           const Vector<FontDescriptionRun>& fontDescriptions,
59 //                                           FontId defaultFontId,
60 //                                           CharacterIndex startIndex,
61 //                                           Length numberOfCharacters,
62 //                                           Vector<FontRun>& fonts );
63
64 //////////////////////////////////////////////////////////
65
66 namespace
67 {
68
69 const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
70 const unsigned int EMOJI_FONT_SIZE = 3968u;
71 const unsigned int NON_DEFAULT_FONT_SIZE = 40u;
72
73 struct MergeFontDescriptionsData
74 {
75   std::string description;                                 ///< Description of the experiment.
76   Vector<FontDescriptionRun> fontDescriptionRuns;          ///< The font description runs.
77   TextAbstraction::FontDescription defaultFontDescription; ///< The default font description.
78   TextAbstraction::PointSize26Dot6 defaultPointSize;       ///< The default point size.
79   unsigned int startIndex;                                 ///< The start index.
80   unsigned int numberOfCharacters;                         ///< The number of characters.
81   Vector<FontId> expectedFontIds;                          ///< The expected font ids.
82 };
83
84 struct ScriptsData
85 {
86   std::string description;         ///< Description of the experiment.
87   std::string text;                ///< Input text.
88   unsigned int index;              ///< The index of the first character to update the script.
89   unsigned int numberOfCharacters; ///< The numbers of characters to update the script.
90   Vector<ScriptRun> scriptRuns;    ///< Expected script runs.
91 };
92
93 struct ValidateFontsData
94 {
95   std::string                description;         ///< Description of the experiment.
96   std::string                text;                ///< Input text.
97   std::string                defaultFont;         ///< The default font.
98   unsigned int               defaultFontSize;     ///< The default font size.
99   unsigned int               index;               ///< The index of the first character to update the script.
100   unsigned int               numberOfCharacters;  ///< The numbers of characters to update the script.
101   Vector<FontDescriptionRun> fontDescriptionRuns; ///< The font description runs.
102   Vector<FontRun>            fontRuns;            ///< The expected font runs.
103 };
104
105 //////////////////////////////////////////////////////////
106
107 bool MergeFontDescriptionsTest( const MergeFontDescriptionsData& data )
108 {
109   Vector<FontId> fontIds;
110   fontIds.Resize( data.startIndex + data.numberOfCharacters, 0u );
111
112   MergeFontDescriptions( data.fontDescriptionRuns,
113                          fontIds,
114                          data.defaultFontDescription,
115                          data.defaultPointSize,
116                          data.startIndex,
117                          data.numberOfCharacters );
118
119   if( fontIds.Count() != data.expectedFontIds.Count() )
120   {
121     std::cout << data.description << " Different number of font ids : " << fontIds.Count() << ", expected : " << data.expectedFontIds.Count() << std::endl;
122     return false;
123   }
124
125   for( unsigned int index = 0u; index < fontIds.Count(); ++index )
126   {
127     if( fontIds[index] != data.expectedFontIds[index] )
128     {
129       std::cout << data.description << " Different font id at index : " << index << ", font id : " << fontIds[index] << ", expected : " << data.expectedFontIds[index] << std::endl;
130       std::cout << "           font ids : ";
131       for( unsigned int i=0;i<fontIds.Count();++i)
132       {
133         std::cout << fontIds[i] << " ";
134       }
135       std::cout << std::endl;
136       std::cout << "  expected font ids : ";
137       for( unsigned int i=0;i<data.expectedFontIds.Count();++i)
138       {
139         std::cout << data.expectedFontIds[i] << " ";
140       }
141       std::cout << std::endl;
142       return false;
143     }
144   }
145
146   return true;
147 }
148
149 bool ScriptsTest( const ScriptsData& data )
150 {
151   MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
152
153   // 1) Convert to utf32
154   Vector<Character> utf32;
155   utf32.Resize( data.text.size() );
156
157   const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
158                                                    data.text.size(),
159                                                    &utf32[0u] );
160   utf32.Resize( numberOfCharacters );
161
162   // 2) Set the script info.
163   Vector<ScriptRun> scripts;
164   multilanguageSupport.SetScripts( utf32,
165                                    0u,
166                                    numberOfCharacters,
167                                    scripts );
168
169   if( ( 0u != data.index ) ||
170       ( numberOfCharacters != data.numberOfCharacters ) )
171   {
172     // 3) Clear the scripts.
173     ClearCharacterRuns( data.index,
174                         data.index + data.numberOfCharacters - 1u,
175                         scripts );
176
177     multilanguageSupport.SetScripts( utf32,
178                                      data.index,
179                                      data.numberOfCharacters,
180                                      scripts );
181   }
182
183   // 4) Compare the results.
184
185   tet_printf( "Testing %s\n", data.description.c_str() );
186   if( scripts.Count() != data.scriptRuns.Count() )
187   {
188     tet_printf("ScriptsTest FAIL: different number of scripts. %d, should be %d\n", scripts.Count(), data.scriptRuns.Count() );
189     return false;
190   }
191
192   for( unsigned int index = 0u; index < scripts.Count(); ++index )
193   {
194     const ScriptRun& scriptRun1 = scripts[index];
195     const ScriptRun& scriptRun2 = data.scriptRuns[index];
196
197     if( scriptRun1.characterRun.characterIndex != scriptRun2.characterRun.characterIndex )
198     {
199       tet_printf("ScriptsTest FAIL: different character index. %d, should be %d\n", scriptRun1.characterRun.characterIndex, scriptRun2.characterRun.characterIndex );
200       return false;
201     }
202
203     if( scriptRun1.characterRun.numberOfCharacters != scriptRun2.characterRun.numberOfCharacters )
204     {
205       tet_printf("ScriptsTest FAIL: different number of characters. %d, should be %d\n", scriptRun1.characterRun.numberOfCharacters, scriptRun2.characterRun.numberOfCharacters );
206       return false;
207     }
208
209     if( scriptRun1.script != scriptRun2.script )
210     {
211       tet_printf("ScriptsTest FAIL: different script. %s, should be %s\n", TextAbstraction::ScriptName[scriptRun1.script], TextAbstraction::ScriptName[scriptRun2.script] );
212       return false;
213     }
214   }
215
216   return true;
217 }
218
219 bool ValidateFontTest( const ValidateFontsData& data )
220 {
221   MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
222   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
223
224   // 1) Convert to utf32
225   Vector<Character> utf32;
226   utf32.Resize( data.text.size() );
227
228   const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
229                                                    data.text.size(),
230                                                    &utf32[0u] );
231   utf32.Resize( numberOfCharacters );
232
233   // 2) Set the script info.
234   Vector<ScriptRun> scripts;
235   multilanguageSupport.SetScripts( utf32,
236                                    0u,
237                                    numberOfCharacters,
238                                    scripts );
239
240   char* pathNamePtr = get_current_dir_name();
241   const std::string pathName( pathNamePtr );
242   free( pathNamePtr );
243
244   // Get the default font id.
245   const FontId defaultFontId = fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + data.defaultFont,
246                                                      data.defaultFontSize );
247
248   Vector<FontRun> fontRuns;
249
250   // 3) Validate the fonts.
251   multilanguageSupport.ValidateFonts( utf32,
252                                       scripts,
253                                       data.fontDescriptionRuns,
254                                       defaultFontId,
255                                       0u,
256                                       numberOfCharacters,
257                                       fontRuns );
258
259   if( ( 0u != data.index ) ||
260       ( numberOfCharacters != data.numberOfCharacters ) )
261   {
262     // 4) Clear the fonts.
263     ClearCharacterRuns( data.index,
264                         data.index + data.numberOfCharacters - 1u,
265                         fontRuns );
266
267     multilanguageSupport.ValidateFonts( utf32,
268                                         scripts,
269                                         data.fontDescriptionRuns,
270                                         defaultFontId,
271                                         data.index,
272                                         data.numberOfCharacters,
273                                         fontRuns );
274   }
275
276   // 5) Compare the results.
277   if( data.fontRuns.Count() != fontRuns.Count() )
278   {
279     std::cout << "  Different number of font runs : " << fontRuns.Count() << ", expected : " << data.fontRuns.Count() << std::endl;
280     return false;
281   }
282
283
284   for( unsigned int index = 0; index < data.fontRuns.Count(); ++index )
285   {
286     const FontRun& run = fontRuns[index];
287     const FontRun& expectedRun = data.fontRuns[index];
288
289     if( run.characterRun.characterIndex != expectedRun.characterRun.characterIndex )
290     {
291       std::cout << "  character run : " << index << ", index : " << run.characterRun.characterIndex << ", expected : " << expectedRun.characterRun.characterIndex << std::endl;
292       return false;
293     }
294     if( run.characterRun.numberOfCharacters != expectedRun.characterRun.numberOfCharacters )
295     {
296       std::cout << "  character run : " << index << ", num chars : " << run.characterRun.numberOfCharacters << ", expected : " << expectedRun.characterRun.numberOfCharacters << std::endl;
297       return false;
298     }
299     if( run.fontId != expectedRun.fontId )
300     {
301       std::cout << "  character run : " << index << ", font : " << run.fontId << ", expected : " << expectedRun.fontId << std::endl;
302       return false;
303     }
304   }
305
306   return true;
307 }
308
309 } // namespace
310
311 int UtcDaliTextGetScript(void)
312 {
313   ToolkitTestApplication application;
314   tet_infoline(" UtcDaliTextGetScript");
315
316   Script script = TextAbstraction::LATIN;
317
318   // Text with no scripts.
319   Vector<ScriptRun> scriptRuns;
320   Vector<ScriptRun>::ConstIterator scriptRunIt = scriptRuns.Begin();
321   script = GetScript( 0u,
322                       scriptRunIt,
323                       scriptRuns.End() );
324
325   DALI_TEST_CHECK( TextAbstraction::UNKNOWN == script );
326
327   const unsigned int numberOfCharacters = 7u;
328   // Add scripts.
329   ScriptRun scriptRun01 =
330   {
331     {
332       0u,
333       2u,
334     },
335     TextAbstraction::LATIN
336   };
337   ScriptRun scriptRun02 =
338   {
339     {
340       2u,
341       2u,
342     },
343     TextAbstraction::HEBREW
344   };
345   ScriptRun scriptRun03 =
346   {
347     {
348       4u,
349       2u,
350     },
351     TextAbstraction::ARABIC
352   };
353   scriptRuns.PushBack( scriptRun01 );
354   scriptRuns.PushBack( scriptRun02 );
355   scriptRuns.PushBack( scriptRun03 );
356
357   // Expected results
358   TextAbstraction::Script expectedScripts[]=
359   {
360     TextAbstraction::LATIN,
361     TextAbstraction::LATIN,
362     TextAbstraction::HEBREW,
363     TextAbstraction::HEBREW,
364     TextAbstraction::ARABIC,
365     TextAbstraction::ARABIC,
366     TextAbstraction::UNKNOWN
367   };
368
369   scriptRunIt = scriptRuns.Begin();
370   for( unsigned int index = 0u; index < numberOfCharacters; ++index )
371   {
372     script = GetScript( index,
373                         scriptRunIt,
374                         scriptRuns.End() );
375
376     DALI_TEST_CHECK( expectedScripts[index] == script );
377   }
378   DALI_TEST_CHECK( scriptRunIt == scriptRuns.End() );
379
380   tet_result(TET_PASS);
381   END_TEST;
382 }
383
384 int UtcDaliTextMergeFontDescriptions(void)
385 {
386   ToolkitTestApplication application;
387   tet_infoline(" UtcDaliTextMergeFontDescriptions");
388
389   // Load some fonts.
390
391   char* pathNamePtr = get_current_dir_name();
392   const std::string pathName( pathNamePtr );
393   free( pathNamePtr );
394
395   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
396   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf" );
397   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif.ttf" );
398   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif.ttf", NON_DEFAULT_FONT_SIZE );
399   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif-Bold.ttf" );
400   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif-Italic.ttf" );
401
402   // To test the font width as GetFontId() with the font file path can't cache the width property.
403   TextAbstraction::FontDescription widthDescription;
404   widthDescription.path = "";
405   widthDescription.family = "DejaVu Serif";
406   widthDescription.weight = TextAbstraction::FontWeight::NORMAL;
407   widthDescription.width = TextAbstraction::FontWidth::EXPANDED;
408   widthDescription.slant = TextAbstraction::FontSlant::NORMAL;
409   fontClient.GetFontId( widthDescription );
410
411   // Test.
412
413   TextAbstraction::FontDescription defaultFontDescription01;
414   Vector<FontDescriptionRun> fontDescriptionRuns01;
415   Vector<FontId> expectedFontIds01;
416
417   TextAbstraction::FontDescription defaultFontDescription02;
418   Vector<FontDescriptionRun> fontDescriptionRuns02;
419   Vector<FontId> expectedFontIds02;
420   expectedFontIds02.PushBack( 0u );
421   expectedFontIds02.PushBack( 0u );
422
423   TextAbstraction::FontDescription defaultFontDescription03;
424   defaultFontDescription03.family = "DejaVu Serif";
425   Vector<FontDescriptionRun> fontDescriptionRuns03;
426
427   FontDescriptionRun fontDescription0301 =
428   {
429     {
430       0u,
431       2u
432     },
433     const_cast<char*>( "DejaVu Sans" ),
434     11u,
435     TextAbstraction::FontWeight::NORMAL,
436     TextAbstraction::FontWidth::NORMAL,
437     TextAbstraction::FontSlant::NORMAL,
438     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
439     true,
440     false,
441     false,
442     false,
443     false
444   };
445   FontDescriptionRun fontDescription0302 =
446   {
447     {
448       2u,
449       2u
450     },
451     NULL,
452     0u,
453     TextAbstraction::FontWeight::NORMAL,
454     TextAbstraction::FontWidth::NORMAL,
455     TextAbstraction::FontSlant::ITALIC,
456     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
457     false,
458     false,
459     false,
460     true,
461     false
462   };
463   FontDescriptionRun fontDescription0303 =
464   {
465     {
466       4u,
467       2u
468     },
469     NULL,
470     0u,
471     TextAbstraction::FontWeight::BOLD,
472     TextAbstraction::FontWidth::NORMAL,
473     TextAbstraction::FontSlant::NORMAL,
474     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
475     false,
476     true,
477     false,
478     false,
479     false
480   };
481   FontDescriptionRun fontDescription0304 =
482   {
483     {
484       6u,
485       2u
486     },
487     NULL,
488     0u,
489     TextAbstraction::FontWeight::NORMAL,
490     TextAbstraction::FontWidth::NORMAL,
491     TextAbstraction::FontSlant::NORMAL,
492     NON_DEFAULT_FONT_SIZE,
493     false,
494     false,
495     false,
496     false,
497     true
498   };
499   FontDescriptionRun fontDescription0305 =
500   {
501     {
502       8u,
503       2u
504     },
505     NULL,
506     0u,
507     TextAbstraction::FontWeight::NORMAL,
508     TextAbstraction::FontWidth::EXPANDED,
509     TextAbstraction::FontSlant::NORMAL,
510     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
511     false,
512     false,
513     true,
514     false,
515     false
516   };
517
518   fontDescriptionRuns03.PushBack( fontDescription0301 );
519   fontDescriptionRuns03.PushBack( fontDescription0302 );
520   fontDescriptionRuns03.PushBack( fontDescription0303 );
521   fontDescriptionRuns03.PushBack( fontDescription0304 );
522   fontDescriptionRuns03.PushBack( fontDescription0305 );
523
524   Vector<FontId> expectedFontIds03;
525   expectedFontIds03.PushBack( 1u );
526   expectedFontIds03.PushBack( 1u );
527   expectedFontIds03.PushBack( 5u );
528   expectedFontIds03.PushBack( 5u );
529   expectedFontIds03.PushBack( 4u );
530   expectedFontIds03.PushBack( 4u );
531   expectedFontIds03.PushBack( 3u );
532   expectedFontIds03.PushBack( 3u );
533   expectedFontIds03.PushBack( 6u );
534   expectedFontIds03.PushBack( 6u );
535
536   const MergeFontDescriptionsData data[] =
537   {
538     {
539       "void text.",
540       fontDescriptionRuns01,
541       defaultFontDescription01,
542       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
543       0u,
544       0u,
545       expectedFontIds01
546     },
547     {
548       "No description runs.",
549       fontDescriptionRuns02,
550       defaultFontDescription02,
551       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
552       0u,
553       2u,
554       expectedFontIds02
555     },
556     {
557       "Some description runs.",
558       fontDescriptionRuns03,
559       defaultFontDescription03,
560       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
561       0u,
562       10u,
563       expectedFontIds03
564     }
565   };
566   const unsigned int numberOfTests = 3u;
567
568   for( unsigned int index = 0u; index < numberOfTests; ++index )
569   {
570     if( !MergeFontDescriptionsTest( data[index] ) )
571     {
572       tet_result(TET_FAIL);
573     }
574   }
575
576   tet_result(TET_PASS);
577   END_TEST;
578 }
579
580 int UtcDaliTextMultiLanguageConstructor(void)
581 {
582   ToolkitTestApplication application;
583   tet_infoline(" UtcDaliTextMultiLanguageConstructor");
584
585   MultilanguageSupport multilanguageSupport;
586   DALI_TEST_CHECK( !multilanguageSupport );
587
588   MultilanguageSupport multilanguageSupport1 = MultilanguageSupport::Get();
589   DALI_TEST_CHECK( multilanguageSupport1 );
590
591   // To increase coverage.
592   MultilanguageSupport multilanguageSupport2 = MultilanguageSupport::Get();
593   DALI_TEST_CHECK( multilanguageSupport2 );
594
595   DALI_TEST_CHECK( multilanguageSupport1 == multilanguageSupport2 );
596
597   tet_result(TET_PASS);
598   END_TEST;
599 }
600
601 int UtcDaliTextMultiLanguageSetScripts(void)
602 {
603   ToolkitTestApplication application;
604   tet_infoline(" UtcDaliTextMultiLanguageSetScripts" );
605
606   // Void text.
607   Vector<ScriptRun> scriptRuns00;
608
609   // Hello world.
610   Vector<ScriptRun> scriptRuns01;
611   ScriptRun scriptRun0100 =
612   {
613     {
614       0u,
615       11u,
616     },
617     TextAbstraction::LATIN
618   };
619   scriptRuns01.PushBack( scriptRun0100 );
620
621   // Mix of LTR '\n'and RTL
622   Vector<ScriptRun> scriptRuns02;
623   ScriptRun scriptRun0200 =
624   {
625     {
626       0u,
627       12u,
628     },
629     TextAbstraction::LATIN
630   };
631   ScriptRun scriptRun0201 =
632   {
633     {
634       12u,
635       13u,
636     },
637     TextAbstraction::ARABIC
638   };
639   scriptRuns02.PushBack( scriptRun0200 );
640   scriptRuns02.PushBack( scriptRun0201 );
641
642   // Mix of RTL '\n'and LTR
643   Vector<ScriptRun> scriptRuns03;
644   ScriptRun scriptRun0300 =
645   {
646     {
647       0u,
648       14u,
649     },
650     TextAbstraction::ARABIC
651   };
652   ScriptRun scriptRun0301 =
653   {
654     {
655       14u,
656       11u,
657     },
658     TextAbstraction::LATIN
659   };
660   scriptRuns03.PushBack( scriptRun0300 );
661   scriptRuns03.PushBack( scriptRun0301 );
662
663   // White spaces. At the beginning of the text.
664   Vector<ScriptRun> scriptRuns04;
665   ScriptRun scriptRun0400 =
666   {
667     {
668       0u,
669       16u,
670     },
671     TextAbstraction::LATIN
672   };
673   scriptRuns04.PushBack( scriptRun0400 );
674
675   // White spaces. At the end of the text.
676   Vector<ScriptRun> scriptRuns05;
677   ScriptRun scriptRun0500 =
678   {
679     {
680       0u,
681       16u,
682     },
683     TextAbstraction::LATIN
684   };
685   scriptRuns05.PushBack( scriptRun0500 );
686
687   // White spaces. At the middle of the text.
688   Vector<ScriptRun> scriptRuns06;
689   ScriptRun scriptRun0600 =
690   {
691     {
692       0u,
693       16u,
694     },
695     TextAbstraction::LATIN
696   };
697   scriptRuns06.PushBack( scriptRun0600 );
698
699   // White spaces between different scripts.
700   Vector<ScriptRun> scriptRuns07;
701   ScriptRun scriptRun0700 =
702   {
703     {
704       0u,
705       8u,
706     },
707     TextAbstraction::LATIN
708   };
709   ScriptRun scriptRun0701 =
710   {
711     {
712       8u,
713       5u,
714     },
715     TextAbstraction::HANGUL
716   };
717   scriptRuns07.PushBack( scriptRun0700 );
718   scriptRuns07.PushBack( scriptRun0701 );
719
720   // White spaces between different scripts and differetn directions. Starting LTR.
721   Vector<ScriptRun> scriptRuns08;
722   ScriptRun scriptRun0800 =
723   {
724     {
725       0u,
726       18u,
727     },
728     TextAbstraction::LATIN
729   };
730   ScriptRun scriptRun0801 =
731   {
732     {
733       18u,
734       14u,
735     },
736     TextAbstraction::ARABIC
737   };
738   ScriptRun scriptRun0802 =
739   {
740     {
741       32u,
742       18u,
743     },
744     TextAbstraction::HANGUL
745   };
746   scriptRuns08.PushBack( scriptRun0800 );
747   scriptRuns08.PushBack( scriptRun0801 );
748   scriptRuns08.PushBack( scriptRun0802 );
749
750   // White spaces between different scripts and differetn directions. Starting RTL.
751   Vector<ScriptRun> scriptRuns09;
752   ScriptRun scriptRun0900 =
753   {
754     {
755       0u,
756       21u,
757     },
758     TextAbstraction::ARABIC
759   };
760   ScriptRun scriptRun0901 =
761   {
762     {
763       21u,
764       16u,
765     },
766     TextAbstraction::LATIN
767   };
768   ScriptRun scriptRun0902 =
769   {
770     {
771       37u,
772       10u,
773     },
774     TextAbstraction::HANGUL
775   };
776   ScriptRun scriptRun0903 =
777   {
778     {
779       47u,
780       20u,
781     },
782     TextAbstraction::ARABIC
783   };
784   scriptRuns09.PushBack( scriptRun0900 );
785   scriptRuns09.PushBack( scriptRun0901 );
786   scriptRuns09.PushBack( scriptRun0902 );
787   scriptRuns09.PushBack( scriptRun0903 );
788
789   // Paragraphs with different directions.
790   Vector<ScriptRun> scriptRuns10;
791   ScriptRun scriptRun1000 =
792   {
793     {
794       0u,
795       20u,
796     },
797     TextAbstraction::ARABIC
798   };
799   ScriptRun scriptRun1001 =
800   {
801     {
802       20u,
803       12u,
804     },
805     TextAbstraction::HEBREW
806   };
807   ScriptRun scriptRun1002 =
808   {
809     {
810       32u,
811       17u,
812     },
813     TextAbstraction::ARABIC
814   };
815   ScriptRun scriptRun1003 =
816   {
817     {
818       49u,
819       18u,
820     },
821     TextAbstraction::LATIN
822   };
823   ScriptRun scriptRun1004 =
824   {
825     {
826       67u,
827       14u,
828     },
829     TextAbstraction::HANGUL
830   };
831   ScriptRun scriptRun1005 =
832   {
833     {
834       81u,
835       19u,
836     },
837     TextAbstraction::ARABIC
838   };
839   ScriptRun scriptRun1006 =
840   {
841     {
842       100u,
843       13u,
844     },
845     TextAbstraction::LATIN
846   };
847   ScriptRun scriptRun1007 =
848   {
849     {
850       113u,
851       16u,
852     },
853     TextAbstraction::HEBREW
854   };
855   ScriptRun scriptRun1008 =
856   {
857     {
858       129u,
859       20u,
860     },
861     TextAbstraction::LATIN
862   };
863   ScriptRun scriptRun1009 =
864   {
865     {
866       149u,
867       14u,
868     },
869     TextAbstraction::ARABIC
870   };
871   ScriptRun scriptRun1010 =
872   {
873     {
874       163u,
875       18u,
876     },
877     TextAbstraction::HANGUL
878   };
879   ScriptRun scriptRun1011 =
880   {
881     {
882       181u,
883       17u,
884     },
885     TextAbstraction::HANGUL
886   };
887   scriptRuns10.PushBack( scriptRun1000 );
888   scriptRuns10.PushBack( scriptRun1001 );
889   scriptRuns10.PushBack( scriptRun1002 );
890   scriptRuns10.PushBack( scriptRun1003 );
891   scriptRuns10.PushBack( scriptRun1004 );
892   scriptRuns10.PushBack( scriptRun1005 );
893   scriptRuns10.PushBack( scriptRun1006 );
894   scriptRuns10.PushBack( scriptRun1007 );
895   scriptRuns10.PushBack( scriptRun1008 );
896   scriptRuns10.PushBack( scriptRun1009 );
897   scriptRuns10.PushBack( scriptRun1010 );
898   scriptRuns10.PushBack( scriptRun1011 );
899
900   // Paragraphs with no scripts mixed with paragraphs with scripts.
901   Vector<ScriptRun> scriptRuns11;
902   ScriptRun scriptRun1100 =
903   {
904     {
905       0u,
906       3u,
907     },
908     TextAbstraction::LATIN
909   };
910   ScriptRun scriptRun1101 =
911   {
912     {
913       3u,
914       3u,
915     },
916     TextAbstraction::LATIN
917   };
918   ScriptRun scriptRun1102 =
919   {
920     {
921       6u,
922       19u,
923     },
924     TextAbstraction::LATIN
925   };
926   ScriptRun scriptRun1103 =
927   {
928     {
929       25u,
930       3u,
931     },
932     TextAbstraction::LATIN
933   };
934   ScriptRun scriptRun1104 =
935   {
936     {
937       28u,
938       3u,
939     },
940     TextAbstraction::LATIN
941   };
942   ScriptRun scriptRun1105 =
943   {
944     {
945       31u,
946       15u,
947     },
948     TextAbstraction::HEBREW
949   };
950   ScriptRun scriptRun1106 =
951   {
952     {
953       46u,
954       2u,
955     },
956     TextAbstraction::LATIN
957   };
958   ScriptRun scriptRun1107 =
959   {
960     {
961       48u,
962       2u,
963     },
964     TextAbstraction::LATIN
965   };
966   ScriptRun scriptRun1108 =
967   {
968     {
969       50u,
970       2u,
971     },
972     TextAbstraction::LATIN
973   };
974   scriptRuns11.PushBack( scriptRun1100 );
975   scriptRuns11.PushBack( scriptRun1101 );
976   scriptRuns11.PushBack( scriptRun1102 );
977   scriptRuns11.PushBack( scriptRun1103 );
978   scriptRuns11.PushBack( scriptRun1104 );
979   scriptRuns11.PushBack( scriptRun1105 );
980   scriptRuns11.PushBack( scriptRun1106 );
981   scriptRuns11.PushBack( scriptRun1107 );
982   scriptRuns11.PushBack( scriptRun1108 );
983
984   // Paragraphs with no scripts.
985   Vector<ScriptRun> scriptRuns12;
986   ScriptRun scriptRun1200 =
987   {
988     {
989       0u,
990       3u,
991     },
992     TextAbstraction::LATIN
993   };
994   ScriptRun scriptRun1201 =
995   {
996     {
997       3u,
998       3u,
999     },
1000     TextAbstraction::LATIN
1001   };
1002   ScriptRun scriptRun1202 =
1003   {
1004     {
1005       6u,
1006       3u,
1007     },
1008     TextAbstraction::LATIN
1009   };
1010   ScriptRun scriptRun1203 =
1011   {
1012     {
1013       9u,
1014       2u,
1015     },
1016     TextAbstraction::LATIN
1017   };
1018   scriptRuns12.PushBack( scriptRun1200 );
1019   scriptRuns12.PushBack( scriptRun1201 );
1020   scriptRuns12.PushBack( scriptRun1202 );
1021   scriptRuns12.PushBack( scriptRun1203 );
1022
1023   Vector<ScriptRun> scriptRuns13;
1024   ScriptRun scriptRun1301 =
1025   {
1026     {
1027       0u,
1028       4u,
1029     },
1030     TextAbstraction::LATIN // An unknown script is transformed to LATIN
1031   };
1032   scriptRuns13.PushBack( scriptRun1301 );
1033
1034   const ScriptsData data[] =
1035   {
1036     {
1037       "void text",
1038       "",
1039       0u,
1040       0u,
1041       scriptRuns00,
1042     },
1043     {
1044       "Easy latin script",
1045       "Hello world",
1046       0u,
1047       11u,
1048       scriptRuns01,
1049     },
1050     {
1051       "Mix of LTR '\\n'and RTL",
1052       "Hello world\nمرحبا بالعالم",
1053       0u,
1054       25u,
1055       scriptRuns02,
1056     },
1057     {
1058       "Update mix of LTR '\\n'and RTL. Update LTR",
1059       "Hello world\nمرحبا بالعالم",
1060       0u,
1061       12u,
1062       scriptRuns02,
1063     },
1064     {
1065       "Update mix of LTR '\\n'and RTL. Update RTL",
1066       "Hello world\nمرحبا بالعالم",
1067       12u,
1068       13u,
1069       scriptRuns02,
1070     },
1071     {
1072       "Mix of RTL '\\n'and LTR",
1073       "مرحبا بالعالم\nHello world",
1074       0u,
1075       25u,
1076       scriptRuns03,
1077     },
1078     {
1079       "Update mix of RTL '\\n'and LTR. Update RTL",
1080       "مرحبا بالعالم\nHello world",
1081       0u,
1082       14u,
1083       scriptRuns03,
1084     },
1085     {
1086       "Update mix of RTL '\\n'and LTR. Update LTR",
1087       "مرحبا بالعالم\nHello world",
1088       14u,
1089       11u,
1090       scriptRuns03,
1091     },
1092     {
1093       "White spaces. At the beginning of the text.",
1094       "    Hello world.",
1095       0u,
1096       16u,
1097       scriptRuns04,
1098     },
1099     {
1100       "White spaces. At the end of the text.",
1101       "Hello world.    ",
1102       0u,
1103       16u,
1104       scriptRuns05,
1105     },
1106     {
1107       "White spaces. At the middle of the text.",
1108       "Hello     world.",
1109       0u,
1110       16u,
1111       scriptRuns06,
1112     },
1113     {
1114       "White spaces between different scripts.",
1115       "  Hel   세계   ",
1116       0u,
1117       13u,
1118       scriptRuns07,
1119     },
1120     {
1121       "White spaces between different scripts and differetn directions. Starting LTR.",
1122       "  Hello   world   مرحبا  بالعالم     안녕하세요   세계   ",
1123       0u,
1124       50u,
1125       scriptRuns08,
1126     },
1127     {
1128       "White spaces between different scripts and differetn directions. Starting RTL.",
1129       "   مرحبا  بالعالم    Hello   world   안녕하세요   세계   مرحبا  بالعالم   ",
1130       0u,
1131       67u,
1132       scriptRuns09
1133     },
1134     {
1135       "Paragraphs with different directions.",
1136       "   مرحبا  بالعالم   שלום עולם   مرحبا  بالعالم  \n "
1137       " Hello   world   안녕하세요   세계   \n "
1138       "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
1139       " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
1140       "   안녕하세요   세계   ",
1141       0u,
1142       198u,
1143       scriptRuns10
1144     },
1145     {
1146       "Update paragraphs with different directions. Update initial paragraphs.",
1147       "   مرحبا  بالعالم   שלום עולם   مرحبا  بالعالم  \n "
1148       " Hello   world   안녕하세요   세계   \n "
1149       "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
1150       " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
1151       "   안녕하세요   세계   ",
1152       0u,
1153       81u,
1154       scriptRuns10
1155     },
1156     {
1157       "Update paragraphs with different directions. Update middle paragraphs.",
1158       "   مرحبا  بالعالم   שלום עולם   مرحبا  بالعالم  \n "
1159       " Hello   world   안녕하세요   세계   \n "
1160       "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
1161       " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
1162       "   안녕하세요   세계   ",
1163       49u,
1164       80u,
1165       scriptRuns10
1166     },
1167     {
1168       "Update paragraphs with different directions. Update final paragraphs.",
1169       "   مرحبا  بالعالم   שלום עולם   مرحبا  بالعالم  \n "
1170       " Hello   world   안녕하세요   세계   \n "
1171       "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
1172       " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
1173       "   안녕하세요   세계   ",
1174       129u,
1175       69u,
1176       scriptRuns10
1177     },
1178     {
1179       "Paragraphs with no scripts mixed with paragraphs with scripts.",
1180       "  \n  \n   Hello   world  \n  \n  \n   שלום עולם  \n \n \n  ",
1181       0u,
1182       52u,
1183       scriptRuns11
1184     },
1185     {
1186       "Paragraphs with no scripts.",
1187       "  \n  \n  \n  ",
1188       0u,
1189       11u,
1190       scriptRuns12
1191     },
1192     {
1193       "Update paragraphs with no scripts. Update initial paragraphs.",
1194       "  \n  \n  \n  ",
1195       0u,
1196       3u,
1197       scriptRuns12
1198     },
1199     {
1200       "Update paragraphs with no scripts. Update middle paragraphs.",
1201       "  \n  \n  \n  ",
1202       3u,
1203       6u,
1204       scriptRuns12
1205     },
1206     {
1207       "Update paragraphs with no scripts. Update final paragraphs.",
1208       "  \n  \n  \n  ",
1209       9u,
1210       2u,
1211       scriptRuns12
1212     },
1213     {
1214       "Unknown scripts.",
1215       "ᚩᚯᚱᚸ", // Runic script not currentlu supported.
1216       0u,
1217       4u,
1218       scriptRuns13
1219     }
1220   };
1221   const unsigned int numberOfTests = 24u;
1222
1223   for( unsigned int index = 0u; index < numberOfTests; ++index )
1224   {
1225     if( !ScriptsTest( data[index] ) )
1226     {
1227       tet_result(TET_FAIL);
1228     }
1229   }
1230
1231   tet_result(TET_PASS);
1232   END_TEST;
1233 }
1234
1235 int UtcDaliTextMultiLanguageValidateFonts01(void)
1236 {
1237   ToolkitTestApplication application;
1238   tet_infoline(" UtcDaliTextMultiLanguageValidateFonts");
1239
1240   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
1241
1242   char* pathNamePtr = get_current_dir_name();
1243   const std::string pathName( pathNamePtr );
1244   free( pathNamePtr );
1245
1246   // Load some fonts.
1247   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
1248   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" );
1249   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenColorEmoji.ttf", EMOJI_FONT_SIZE );
1250
1251   // Font id 1 --> TizenSansArabicRegular.ttf
1252   // Font id 2 --> TizenSansHebrewRegular.ttf
1253   // Font id 3 --> TizenColorEmoji.ttf
1254   // Font id 4 --> (default)
1255
1256   Vector<FontRun> fontRuns01;
1257   Vector<FontDescriptionRun> fontDescriptions01;
1258
1259   FontRun fontRun0201 =
1260   {
1261     {
1262       0u,
1263       11u
1264     },
1265     4u
1266   };
1267   Vector<FontRun> fontRuns02;
1268   fontRuns02.PushBack( fontRun0201 );
1269
1270   FontDescriptionRun fontDescription0201 =
1271   {
1272     {
1273       0u,
1274       11u
1275     },
1276     const_cast<char*>( "TizenSans" ),
1277     9u,
1278     TextAbstraction::FontWeight::NORMAL,
1279     TextAbstraction::FontWidth::NORMAL,
1280     TextAbstraction::FontSlant::NORMAL,
1281     0u,
1282     true,
1283     false,
1284     false,
1285     false,
1286     false
1287   };
1288   Vector<FontDescriptionRun> fontDescriptions02;
1289   fontDescriptions02.PushBack( fontDescription0201 );
1290
1291   FontRun fontRun0301 =
1292   {
1293     {
1294       0u,
1295       12u
1296     },
1297     4u
1298   };
1299   FontRun fontRun0302 =
1300   {
1301     {
1302       12u,
1303       12u
1304     },
1305     4u
1306   };
1307   FontRun fontRun0303 =
1308   {
1309     {
1310       24u,
1311       4u
1312     },
1313     4u
1314   };
1315   Vector<FontRun> fontRuns03;
1316   fontRuns03.PushBack( fontRun0301 );
1317   fontRuns03.PushBack( fontRun0302 );
1318   fontRuns03.PushBack( fontRun0303 );
1319
1320   Vector<FontDescriptionRun> fontDescriptions03;
1321
1322   FontRun fontRun0701 =
1323   {
1324     {
1325       0u,
1326       4u
1327     },
1328     2u
1329   };
1330   FontRun fontRun0702 =
1331   {
1332     {
1333       4u,
1334       1u
1335     },
1336     4u
1337   };
1338   FontRun fontRun0703 =
1339   {
1340     {
1341       5u,
1342       4u
1343     },
1344     2u
1345   };
1346   Vector<FontRun> fontRuns07;
1347   fontRuns07.PushBack( fontRun0701 );
1348   fontRuns07.PushBack( fontRun0702 );
1349   fontRuns07.PushBack( fontRun0703 );
1350
1351   FontDescriptionRun fontDescription0701 =
1352   {
1353     {
1354       0u,
1355       4u
1356     },
1357     const_cast<char*>( "TizenSansHebrew" ),
1358     15u,
1359     TextAbstraction::FontWeight::NORMAL,
1360     TextAbstraction::FontWidth::NORMAL,
1361     TextAbstraction::FontSlant::NORMAL,
1362     0u,
1363     true,
1364     false,
1365     false,
1366     false,
1367     false
1368   };
1369   FontDescriptionRun fontDescription0702 =
1370   {
1371     {
1372       5u,
1373       4u
1374     },
1375     const_cast<char*>( "TizenSansHebrew" ),
1376     15u,
1377     TextAbstraction::FontWeight::NORMAL,
1378     TextAbstraction::FontWidth::NORMAL,
1379     TextAbstraction::FontSlant::NORMAL,
1380     0u,
1381     true,
1382     false,
1383     false,
1384     false,
1385     false
1386   };
1387   Vector<FontDescriptionRun> fontDescriptions07;
1388   fontDescriptions07.PushBack( fontDescription0701 );
1389   fontDescriptions07.PushBack( fontDescription0702 );
1390
1391   FontRun fontRun0801 =
1392   {
1393     {
1394       0u,
1395       9u
1396     },
1397     2u
1398   };
1399   Vector<FontRun> fontRuns08;
1400   fontRuns08.PushBack( fontRun0801 );
1401
1402   Vector<FontDescriptionRun> fontDescriptions08;
1403
1404   FontRun fontRun0901 =
1405   {
1406     {
1407       0u,
1408       4u
1409     },
1410     3u
1411   };
1412   Vector<FontRun> fontRuns09;
1413   fontRuns09.PushBack( fontRun0901 );
1414
1415   Vector<FontDescriptionRun> fontDescriptions09;
1416   FontDescriptionRun fontDescription0901 =
1417   {
1418     {
1419       0u,
1420       4u
1421     },
1422     const_cast<char*>( "TizenColorEmoji" ),
1423     15u,
1424     TextAbstraction::FontWeight::NORMAL,
1425     TextAbstraction::FontWidth::NORMAL,
1426     TextAbstraction::FontSlant::NORMAL,
1427     EMOJI_FONT_SIZE,
1428     true,
1429     false,
1430     false,
1431     false,
1432     true
1433   };
1434   fontDescriptions09.PushBack( fontDescription0901 );
1435
1436   const ValidateFontsData data[] =
1437   {
1438     {
1439       "void text.",
1440       "",
1441       "/tizen/TizenSansRegular.ttf",
1442       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1443       0u,
1444       0u,
1445       fontDescriptions01,
1446       fontRuns01
1447     },
1448     {
1449       "Easy latin script.",
1450       "Hello world",
1451       "/tizen/TizenSansRegular.ttf",
1452       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1453       0u,
1454       11u,
1455       fontDescriptions02,
1456       fontRuns02
1457     },
1458     {
1459       "Different paragraphs.",
1460       "Hello world\nhello world\ndemo",
1461       "/tizen/TizenSansRegular.ttf",
1462       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1463       0u,
1464       28u,
1465       fontDescriptions03,
1466       fontRuns03
1467     },
1468     {
1469       "Different paragraphs. Update the initial paragraph.",
1470       "Hello world\nhello world\ndemo",
1471       "/tizen/TizenSansRegular.ttf",
1472       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1473       0u,
1474       12u,
1475       fontDescriptions03,
1476       fontRuns03
1477     },
1478     {
1479       "Different paragraphs. Update the middle paragraph.",
1480       "Hello world\nhello world\ndemo",
1481       "/tizen/TizenSansRegular.ttf",
1482       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1483       12u,
1484       12u,
1485       fontDescriptions03,
1486       fontRuns03
1487     },
1488     {
1489       "Different paragraphs. Update the final paragraph.",
1490       "Hello world\nhello world\ndemo",
1491       "/tizen/TizenSansRegular.ttf",
1492       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1493       24u,
1494       4u,
1495       fontDescriptions03,
1496       fontRuns03
1497     },
1498     {
1499       "Hebrew text. Default font: latin",
1500       "שלום עולם",
1501       "/tizen/TizenSansRegular.ttf",
1502       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1503       0u,
1504       9u,
1505       fontDescriptions07,
1506       fontRuns07
1507     },
1508     {
1509       "Hebrew text. Default font: hebrew",
1510       "שלום עולם",
1511       "/tizen/TizenSansHebrewRegular.ttf",
1512       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
1513       0u,
1514       9u,
1515       fontDescriptions08,
1516       fontRuns08
1517     },
1518     {
1519       "Emojis",
1520       "\xF0\x9F\x98\x81\xF0\x9F\x98\x82\xF0\x9F\x98\x83\xF0\x9F\x98\x84",
1521       "/tizen/TizenColorEmoji.ttf",
1522       EMOJI_FONT_SIZE,
1523       0u,
1524       4u,
1525       fontDescriptions09,
1526       fontRuns09
1527     },
1528   };
1529   const unsigned int numberOfTests = 9u;
1530
1531   for( unsigned int index = 0u; index < numberOfTests; ++index )
1532   {
1533     if( !ValidateFontTest( data[index] ) )
1534     {
1535       tet_result(TET_FAIL);
1536     }
1537   }
1538
1539   tet_result(TET_PASS);
1540   END_TEST;
1541 }