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