Merge "Add bidirectional text tct." into devel/master
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-BidirectionalSupport.cpp
1 /*
2  * Copyright (c) 2018 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
21 #include <dali/devel-api/text-abstraction/bidirectional-support.h>
22 #include <dali-toolkit/internal/text/bidirectional-support.h>
23 #include <dali-toolkit/internal/text/character-set-conversion.h>
24 #include <dali-toolkit/internal/text/text-run-container.h>
25 #include <dali-toolkit-test-suite-utils.h>
26 #include <dali-toolkit/dali-toolkit.h>
27 #include <toolkit-text-utils.h>
28
29 using namespace Dali;
30 using namespace Toolkit;
31 using namespace Text;
32
33 // Tests the following functions.
34 //
35 // void SetBidirectionalInfo( const Vector<Character>& text,
36 //                            const Vector<ScriptRun>& scripts,
37 //                            const Vector<LineBreakInfo>& lineBreakInfo,
38 //                            CharacterIndex startIndex,
39 //                            Length numberOfCharacters,
40 //                            Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo )
41 // void ReorderLines( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
42 //                    CharacterIndex startIndex,
43 //                    Length numberOfCharacters,
44 //                    Vector<LineRun>& lineRuns,
45 //                    Vector<BidirectionalLineInfoRun>& lineInfoRuns )
46 // bool GetMirroredText( const Vector<Character>& text,
47 //                       Vector<CharacterDirection>& directions,
48 //                       const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
49 //                       CharacterIndex startIndex,
50 //                       Length numberOfCharacters,
51 //                       Vector<Character>& mirroredText )
52 // void GetCharactersDirection( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
53 //                              CharacterIndex startIndex,
54 //                              Length numberOfCharacters,
55 //                              Vector<CharacterDirection>& directions )
56
57 //////////////////////////////////////////////////////////
58
59 namespace
60 {
61
62 struct SetBidirectionalInfoData
63 {
64   std::string   description;                 ///< Description of the test.
65   std::string   text;                        ///< Input text.
66   unsigned int  startIndex;                  ///< The index from where the model is updated.
67   unsigned int  numberOfCharacters;          ///< The number of characters to update.
68   unsigned int  numberOfParagraphs;          ///< The expected number of bidirectional paragraphs.
69   unsigned int* indices;                     ///< The expected indices to the first character of each paragraph.
70   unsigned int* numberOfParagraphCharacters; ///< The expected number of characters of each paragraph.
71   bool*         directions;                  ///< The expected direction of each paragraph.
72 };
73
74 struct BidiLineData
75 {
76   unsigned int  characterIndex;
77   unsigned int  numberOfCharacters;
78   unsigned int* visualToLogical;
79 };
80
81 struct ReorderLinesData
82 {
83   std::string   description;        ///< Description of the test.
84   std::string   text;               ///< Input text.
85   unsigned int  startIndex;         ///< The index from where the model is updated.
86   unsigned int  numberOfCharacters; ///< The number of characters.
87   unsigned int  numberOfLineInfo;   ///< The number or reordered lines.
88   BidiLineData* bidiLineData;       ///< The bidirectional line info.
89   unsigned int  numberOfLines;      ///< The number of laid-out lines.
90   bool*         lineDirections;     ///< The directions of the lines.
91 };
92
93 struct GetMirroredTextData
94 {
95   std::string  description;        ///< Description of the test.
96   std::string  text;               ///< Input text.
97   unsigned int startIndex;         ///< The index from where the model is updated.
98   unsigned int numberOfCharacters; ///< The number of the characters.
99   std::string  mirroredText;       ///< The expected result.
100 };
101
102 struct GetCharactersDirectionData
103 {
104   std::string  description;            ///< Description of the test.
105   std::string  text;                   ///< Input text.
106   unsigned int startIndex;             ///< The index from where the model is updated.
107   unsigned int numberOfCharacters;     ///< The number of characters.
108   bool*        directions;             ///< The expected directions.
109   bool         markupProcessorEnabled; ///< Enable markup processor to use markup text.
110 };
111
112 bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
113 {
114   // 1) Create the model.
115   LogicalModelPtr logicalModel;
116   VisualModelPtr visualModel;
117   MetricsPtr metrics;
118   Size textArea(100.f, 60.f);
119   Size layoutSize;
120
121   // Create the model.
122   const Vector<FontDescriptionRun> fontDescriptions;
123   const LayoutOptions options;
124   CreateTextModel( data.text,
125                    textArea,
126                    fontDescriptions,
127                    options,
128                    layoutSize,
129                    logicalModel,
130                    visualModel,
131                    metrics,
132                    false );
133
134   // 2) Clear the bidirectional paragraph info data.
135   Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
136   if( 0u != data.numberOfCharacters )
137   {
138     ClearCharacterRuns( data.startIndex,
139                         data.startIndex + data.numberOfCharacters - 1u,
140                         bidirectionalInfo );
141   }
142
143   // 3) Call the SetBidirectionalInfo() function.
144   SetBidirectionalInfo( logicalModel->mText,
145                         logicalModel->mScriptRuns,
146                         logicalModel->mLineBreakInfo,
147                         data.startIndex,
148                         data.numberOfCharacters,
149                         bidirectionalInfo );
150
151   // 4) Compare with the expected results.
152   TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
153
154   if( data.numberOfParagraphs != bidirectionalInfo.Count() )
155   {
156     // Different number of expected bidirectional paragraphs.
157     std::cout << "  Different number of bidi paragraphs : " << bidirectionalInfo.Count() << ", expected : " << data.numberOfParagraphs << std::endl;
158     return false;
159   }
160
161   for( unsigned int index = 0u; index < data.numberOfParagraphs; ++index )
162   {
163     const BidirectionalParagraphInfoRun& run = bidirectionalInfo[index];
164
165     const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection( run.bidirectionalInfoIndex );
166     if( direction != data.directions[index] )
167     {
168       std::cout << "  Different direction" << std::endl;
169       std::cout << "        paragraph : " << index << std::endl;
170       std::cout << "            index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
171       std::cout << "  expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
172       return false;
173     }
174
175     if( run.characterRun.characterIndex != data.indices[index] )
176     {
177       std::cout << "  Different index" << std::endl;
178       std::cout << "        paragraph : " << index << std::endl;
179       std::cout << "            index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
180       std::cout << "  expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
181       return false;
182     }
183     if( run.characterRun.numberOfCharacters != data.numberOfParagraphCharacters[index] )
184     {
185       std::cout << "  Different number of characters" << std::endl;
186       std::cout << "        paragraph : " << index << std::endl;
187       std::cout << "            index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
188       std::cout << "  expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
189       return false;
190     }
191   }
192
193   return true;
194 }
195
196 /**
197  * @brief Frees previously allocated bidirectional resources.
198  *
199  * @param[in] bidirectionalLineInfo Bidirectional info per line.
200  * @param[in] startIndex Index to the first line with bidirectional info to be freed.
201  * @param[in] endIndex Index to the last line with bidirectional info to be freed.
202  */
203 void FreeBidirectionalLineInfoResources( Vector<BidirectionalLineInfoRun> bidirectionalLineInfo,
204                                          uint32_t startIndex,
205                                          uint32_t endIndex )
206 {
207   // Free the allocated memory used to store the conversion table in the bidirectional line info run.
208   for( Vector<BidirectionalLineInfoRun>::Iterator it = bidirectionalLineInfo.Begin() + startIndex,
209          endIt = bidirectionalLineInfo.Begin() + endIndex;
210        it != endIt;
211        ++it )
212   {
213     BidirectionalLineInfoRun& bidiLineInfo = *it;
214
215     free( bidiLineInfo.visualToLogicalMap );
216   }
217 }
218
219 bool ReorderLinesTest( const ReorderLinesData& data )
220 {
221   // 1) Create the model.
222   LogicalModelPtr logicalModel;
223   VisualModelPtr visualModel;
224   MetricsPtr metrics;
225   Size textArea(100.f, 300.f);
226   Size layoutSize;
227
228   // Create the model.
229   const Vector<FontDescriptionRun> fontDescriptions;
230   const LayoutOptions options;
231   CreateTextModel( data.text,
232                    textArea,
233                    fontDescriptions,
234                    options,
235                    layoutSize,
236                    logicalModel,
237                    visualModel,
238                    metrics,
239                    false );
240
241   // 2) Clear the bidirectional line info data.
242   uint32_t startRemoveIndex = logicalModel->mBidirectionalLineInfo.Count();
243   uint32_t endRemoveIndex = startRemoveIndex;
244   ClearCharacterRuns( data.startIndex,
245                       data.startIndex + data.numberOfCharacters - 1u,
246                       logicalModel->mBidirectionalLineInfo,
247                       startRemoveIndex,
248                       endRemoveIndex );
249
250   // Index to the first index to be removed.
251
252   FreeBidirectionalLineInfoResources( logicalModel->mBidirectionalLineInfo, startRemoveIndex, endRemoveIndex );
253   BidirectionalLineInfoRun* bidiLineBuffer = logicalModel->mBidirectionalLineInfo.Begin();
254   logicalModel->mBidirectionalLineInfo.Erase( bidiLineBuffer + startRemoveIndex,
255                                               bidiLineBuffer + endRemoveIndex );
256
257   // 3) Call the function ReorderLines()
258
259   ReorderLines( logicalModel->mBidirectionalParagraphInfo,
260                 data.startIndex,
261                 data.numberOfCharacters,
262                 visualModel->mLines,
263                 logicalModel->mBidirectionalLineInfo );
264
265   // 4) Compare the results.
266
267   if( data.numberOfLineInfo != logicalModel->mBidirectionalLineInfo.Count() )
268   {
269     // Different number of bidirectional lines.
270     std::cout << "  different number of bidi lines : " << logicalModel->mBidirectionalLineInfo.Count() << ", expected : " << data.numberOfLineInfo << std::endl;
271     for( unsigned int index = 0u; index < logicalModel->mBidirectionalLineInfo.Count(); ++index )
272     {
273       const BidirectionalLineInfoRun& run = logicalModel->mBidirectionalLineInfo[index];
274       const BidiLineData& bidiLineData = data.bidiLineData[index];
275
276       std::cout << "  bidi line : " << index << ", index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << std::endl;
277       std::cout << "                      expected index : " << bidiLineData.characterIndex << ", num chars : " << bidiLineData.numberOfCharacters << std::endl;
278     }
279     return false;
280   }
281
282   for( unsigned int index = 0u; index < data.numberOfLineInfo; ++index )
283   {
284     const BidirectionalLineInfoRun& run = logicalModel->mBidirectionalLineInfo[index];
285     const BidiLineData& bidiLineData = data.bidiLineData[index];
286
287     if( bidiLineData.characterIndex != run.characterRun.characterIndex )
288     {
289       std::cout << "  bidi line : " << index << ", index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << std::endl;
290       std::cout << "                      expected index : " << bidiLineData.characterIndex << ", num chars : " << bidiLineData.numberOfCharacters << std::endl;
291       return false;
292     }
293     if( bidiLineData.numberOfCharacters != run.characterRun.numberOfCharacters )
294     {
295       std::cout << "  bidi line : " << index << ", index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << std::endl;
296       std::cout << "                      expected index : " << bidiLineData.characterIndex << ", num chars : " << bidiLineData.numberOfCharacters << std::endl;
297       return false;
298     }
299
300     for( unsigned int i = 0u; i < run.characterRun.numberOfCharacters; ++i )
301     {
302       if( bidiLineData.visualToLogical[i] != run.visualToLogicalMap[i] )
303       {
304         std::cout << "           v2l : ";
305         for( unsigned int i = 0u; i < run.characterRun.numberOfCharacters; ++i )
306         {
307           std::cout << run.visualToLogicalMap[i] << " ";
308         }
309         std::cout << std::endl;
310         std::cout << "  expected v2l : ";
311         for( unsigned int i = 0u; i < run.characterRun.numberOfCharacters; ++i )
312         {
313           std::cout << bidiLineData.visualToLogical[i] << " ";
314         }
315         std::cout << std::endl;
316
317         return false;
318       }
319     }
320   }
321
322   if( data.numberOfLines != visualModel->mLines.Count() )
323   {
324     std::cout << "Different number of lines : " << visualModel->mLines.Count() << ", expected : " << data.numberOfLines << std::endl;
325
326     unsigned int index = 0u;
327     for( Vector<LineRun>::ConstIterator it = visualModel->mLines.Begin(),
328            endIt = visualModel->mLines.End();
329          it != endIt;
330          ++it, ++index )
331     {
332       const LineRun& line = *it;
333
334       if( line.direction != *( data.lineDirections + index ) )
335       {
336         std::cout << "  Different line direction : " << line.direction << ", expected : " << *( data.lineDirections + index ) << std::endl;
337         return false;
338       }
339     }
340   }
341
342   return true;
343 }
344
345 bool GetMirroredTextTest( const GetMirroredTextData& data )
346 {
347   // 1) Create the model.
348   LogicalModelPtr logicalModel;
349   VisualModelPtr visualModel;
350   MetricsPtr metrics;
351   Size textArea(100.f, 60.f);
352   Size layoutSize;
353
354   // Create the model.
355   const Vector<FontDescriptionRun> fontDescriptions;
356   const LayoutOptions options;
357   CreateTextModel( data.text,
358                    textArea,
359                    fontDescriptions,
360                    options,
361                    layoutSize,
362                    logicalModel,
363                    visualModel,
364                    metrics,
365                    false );
366
367   // 2) Call the GetMirroredText() function for the whole text
368   Vector<Character> mirroredText;
369   bool mirrored = false;
370   mirrored = GetMirroredText( logicalModel->mText,
371                               logicalModel->mCharacterDirections,
372                               logicalModel->mBidirectionalParagraphInfo,
373                               0u,
374                               logicalModel->mText.Count(),
375                               mirroredText );
376
377   // 3) Call the GetMirroredText() function for the given index + number of characters
378   mirrored = GetMirroredText( logicalModel->mText,
379                               logicalModel->mCharacterDirections,
380                               logicalModel->mBidirectionalParagraphInfo,
381                               data.startIndex,
382                               data.numberOfCharacters,
383                               mirroredText );
384
385   // 4) Compare the results.
386
387   // Convert to utf8
388   std::string mirroredString;
389   Utf32ToUtf8( mirroredText.Begin(),
390                mirroredText.Count(),
391                mirroredString );
392
393   if( !mirrored && ( mirroredString != data.text ) )
394   {
395     std::cout << "  No mirrored text and mirroredString != data.text." << std::endl;
396     std::cout << "  mirrored string : [" << mirroredString << "]" << std::endl;
397     std::cout << "             text : [" << data.text << "]" << std::endl;
398     return false;
399   }
400
401   if( mirrored && ( mirroredString == data.text ) )
402   {
403     std::cout << "  Mirrored text and mirroredString == data.text." << std::endl;
404     std::cout << "  mirrored string : [" << mirroredString << "]" << std::endl;
405     std::cout << "             text : [" << data.text << "]" << std::endl;
406     return false;
407   }
408
409   if( mirrored && ( mirroredString != data.mirroredText ) )
410   {
411     std::cout << "  Mirrored text and mirroredString != data.mirroredText." << std::endl;
412     std::cout << "  mirrored string : [" << mirroredString << "]" << std::endl;
413     std::cout << "             text : [" << data.mirroredText << "]" << std::endl;
414     return false;
415   }
416
417   return true;
418 }
419
420 bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
421 {
422   // 1) Create the model.
423   LogicalModelPtr logicalModel;
424   VisualModelPtr visualModel;
425   MetricsPtr metrics;
426   Size textArea(100.f, 60.f);
427   Size layoutSize;
428
429   // Create the model.
430   const Vector<FontDescriptionRun> fontDescriptions;
431   const LayoutOptions options;
432   CreateTextModel( data.text,
433                    textArea,
434                    fontDescriptions,
435                    options,
436                    layoutSize,
437                    logicalModel,
438                    visualModel,
439                    metrics,
440                    data.markupProcessorEnabled );
441
442   Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
443
444   // 2) Clear the direction info data.
445   Vector<CharacterDirection>& directions = logicalModel->mCharacterDirections;
446
447   if( directions.Count() >= data.startIndex + data.numberOfCharacters )
448   {
449     directions.Erase( directions.Begin() + data.startIndex,
450                       directions.Begin() + data.startIndex + data.numberOfCharacters );
451   }
452
453   // 3) Call GetCharactersDirection() function.
454
455   GetCharactersDirection( bidirectionalInfo,
456                           logicalModel->mText.Count(),
457                           data.startIndex,
458                           data.numberOfCharacters,
459                           directions );
460
461   for( unsigned int index = 0u; index < logicalModel->mText.Count(); ++index )
462   {
463     if( data.directions[index] != directions[index] )
464     {
465       return false;
466     }
467   }
468
469   return true;
470 }
471
472 } // namespace
473
474 //////////////////////////////////////////////////////////
475
476 int UtcDaliSetBidirectionalInfo(void)
477 {
478   tet_infoline(" UtcDaliSetBidirectionalInfo");
479
480   unsigned int indices01[] = {};
481   unsigned int numberOfCharacters01[] = {};
482   bool         direction01[] = {};
483   unsigned int indices02[] = {};
484   unsigned int numberOfCharacters02[] = {};
485   bool         direction02[] = {};
486   unsigned int indices03[] = { 17u, 48u };
487   unsigned int numberOfCharacters03[] = { 14u, 14u };
488   bool         direction03[] = { true, true };
489   unsigned int indices04[] = { 17u, 31u, 79u };
490   unsigned int numberOfCharacters04[] = { 14u, 48u, 31u };
491   bool         direction04[] = { true, false, true };
492   unsigned int indices05[] = { 17u, 41u, 117u };
493   unsigned int numberOfCharacters05[] = { 24u, 76u, 49u };
494   bool         direction05[] = { true, false, true };
495   unsigned int indices06[] = { 17u, 48u };
496   unsigned int numberOfCharacters06[] = { 14u, 14u };
497   bool         direction06[] = { true, true };
498   unsigned int indices07[] = { 17u, 31u, 79u };
499   unsigned int numberOfCharacters07[] = { 14u, 48u, 31u };
500   bool         direction07[] = { true, false, true };
501   unsigned int indices08[] = { 17u, 41u, 117u };
502   unsigned int numberOfCharacters08[] = { 24u, 76u, 49u };
503   bool         direction08[] = { true, false, true };
504
505   struct SetBidirectionalInfoData data[] =
506   {
507     {
508       "Zero characters",
509       "",
510       0u,
511       0u,
512       0u,
513       indices01,
514       numberOfCharacters01,
515       direction01
516     },
517     {
518       "Some left to right paragraphs",
519       "Hello world\ndemo\n\n",
520       0u,
521       18u,
522       0u,
523       indices02,
524       numberOfCharacters02,
525       direction02
526     },
527     {
528       "A mix of left to right and right to left paragraphs.",
529       "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
530       0u,
531       78u,
532       2u,
533       indices03,
534       numberOfCharacters03,
535       direction03
536     },
537     {
538       "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
539       "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
540       0u,
541       126u,
542       3u,
543       indices04,
544       numberOfCharacters04,
545       direction04
546     },
547     {
548       "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text and a mix of right to left scripts.",
549       "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
550       0u,
551       182u,
552       3u,
553       indices05,
554       numberOfCharacters05,
555       direction05
556     },
557     {
558       "A mix of left to right and right to left paragraphs. Updates a left to right paragraph.",
559       "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
560       31u,
561       17u,
562       2u,
563       indices06,
564       numberOfCharacters06,
565       direction06
566     },
567     {
568       "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
569       "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
570       0u,
571       126u,
572       3u,
573       indices07,
574       numberOfCharacters07,
575       direction07
576     },
577     {
578       "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text and a mix of right to left scripts. Updates initial paragraphs.",
579       "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
580       0u,
581       41u,
582       3u,
583       indices08,
584       numberOfCharacters08,
585       direction08
586     },
587     {
588       "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text and a mix of right to left scripts. Updates mid paragraphs.",
589       "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
590       41u,
591       76u,
592       3u,
593       indices08,
594       numberOfCharacters08,
595       direction08
596     },
597     {
598       "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text and a mix of right to left scripts. Updates from character 85",
599       "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
600       117u,
601       65u,
602       3u,
603       indices08,
604       numberOfCharacters08,
605       direction08
606     },
607   };
608   const unsigned int numberOfTests = 10u;
609
610   for( unsigned int index = 0u; index < numberOfTests; ++index )
611   {
612     ToolkitTestApplication application;
613     if( !SetBidirectionalInfoTest( data[index] ) )
614     {
615       tet_result(TET_FAIL);
616     }
617   }
618
619   tet_result(TET_PASS);
620   END_TEST;
621 }
622
623 int UtcDaliReorderLines(void)
624 {
625   tet_infoline(" UtcDaliSetBidirectionalInfo");
626
627   unsigned int visualToLogical0301[] = { 0u, 1u, 2u, 3u, 4u, 5u, 9u, 8u, 7u, 6u, 10u };
628   unsigned int visualToLogical0302[] = { 3u, 2u, 1u, 0u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
629   unsigned int visualToLogical0303[] = { 0u, 1u, 2u, 3u, 4u };
630   unsigned int visualToLogical0304[] = { 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
631   unsigned int visualToLogical0305[] = { 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
632   unsigned int visualToLogical0306[] = { 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
633   unsigned int visualToLogical0307[] = { 13u, 8u, 9u, 10u, 11u, 12u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
634   unsigned int visualToLogical0308[] = { 5u, 0u, 1u, 2u, 3u, 4u };
635   unsigned int visualToLogical0309[] = { 0u, 1u, 2u, 3u, 4u, 5u, 9u, 8u, 7u, 6u, 10u };
636   unsigned int visualToLogical0310[] = { 3u, 2u, 1u, 0u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
637   unsigned int visualToLogical0311[] = { 0u, 1u, 2u, 3u, 4u };
638   unsigned int visualToLogical0312[] = { 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
639   unsigned int visualToLogical0313[] = { 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
640   unsigned int visualToLogical0314[] = { 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
641   unsigned int visualToLogical0315[] = { 13u, 8u, 9u, 10u, 11u, 12u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
642   unsigned int visualToLogical0316[] = { 0u, 1u, 2u, 3u, 4u };
643
644   BidiLineData bidiLine01[] = {};
645   BidiLineData bidiLine02[] = {};
646   BidiLineData bidiLine03[] = {
647     {
648       17u,
649       11u,
650       visualToLogical0301
651     },
652     {
653       28u,
654       11u,
655       visualToLogical0302
656     },
657     {
658       39u,
659       5u,
660       visualToLogical0303
661     },
662     {
663       44u,
664       13u,
665       visualToLogical0304
666     },
667     {
668       57u,
669       11u,
670       visualToLogical0305
671     },
672     {
673       68u,
674       10u,
675       visualToLogical0306
676     },
677     {
678       78u,
679       14u,
680       visualToLogical0307
681     },
682     {
683       92u,
684       6u,
685       visualToLogical0308
686     },
687     {
688       115u,
689       11u,
690       visualToLogical0309
691     },
692     {
693       126u,
694       11u,
695       visualToLogical0310
696     },
697     {
698       137u,
699       5u,
700       visualToLogical0311
701     },
702     {
703       142u,
704       13u,
705       visualToLogical0312
706     },
707     {
708       155u,
709       11u,
710       visualToLogical0313
711     },
712     {
713       166u,
714       10u,
715       visualToLogical0314
716     },
717     {
718       176u,
719       14u,
720       visualToLogical0315
721     },
722     {
723       190u,
724       5u,
725       visualToLogical0316
726     },
727   };
728
729   bool directions02[] = { false, false, false, false, false, false };
730   bool directions03[] = { false, false, false, false, false, true, true, true, true, true, false, false, false, false, false, true, true, true, true, true };
731
732   struct ReorderLinesData data[] =
733   {
734     {
735       "Zero characters.",
736       "",
737       0u,
738       0u,
739       0u,
740       bidiLine01,
741       0u,
742       NULL
743     },
744     {
745       "Left to right text only.",
746       "Hello world demo\nhello world demo\nhello world demo.",
747       0u,
748       51u,
749       0u,
750       bidiLine02,
751       6u,
752       directions02
753     },
754     {
755       "Bidirectional paragraphs.",
756       "Hello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world\nHello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world",
757       0u,
758       195u,
759       16u,
760       bidiLine03,
761       20u,
762       directions03
763     },
764     {
765       "Bidirectional paragraphs. Update initial paragraphs.",
766       "Hello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world\nHello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world",
767       0u,
768       44u,
769       16u,
770       bidiLine03,
771       20u,
772       directions03
773     },
774     {
775       "Bidirectional paragraphs. Update middle paragraphs.",
776       "Hello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world\nHello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world",
777       44u,
778       54u,
779       16u,
780       bidiLine03,
781       20u,
782       directions03
783     },
784     {
785       "Bidirectional paragraphs. Update final paragraphs.",
786       "Hello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world\nHello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world",
787       142u,
788       53u,
789       16u,
790       bidiLine03,
791       20u,
792       directions03
793     },
794   };
795   const unsigned int numberOfTests = 6u;
796
797   for( unsigned int index = 0u; index < numberOfTests; ++index )
798   {
799     ToolkitTestApplication application;
800     if( !ReorderLinesTest( data[index] ) )
801     {
802       tet_result(TET_FAIL);
803     }
804   }
805
806   tet_result(TET_PASS);
807   END_TEST;
808 }
809
810 int UtcDaliGetMirroredText(void)
811 {
812   tet_infoline(" UtcDaliGetMirroredText");
813
814   struct GetMirroredTextData data[] =
815   {
816     {
817       "Zero characters.",
818       "",
819       0u,
820       0u,
821       ""
822     },
823     {
824       "Left to right characters only.",
825       "Hello world\nhello world demo.",
826       0u,
827       29u,
828       "Hello world\nhello world demo."
829     },
830     {
831       "Right to left characters but with no characters to mirror.",
832       "שלום עולם\nمرحبا بالعالم",
833       0u,
834       23u,
835       "שלום עולם\nمرحبا بالعالم"
836     },
837     {
838       "Right to left characters with some characters to mirror.",
839       "שלום עולם\n(مرحبا بالعالم)",
840       0u,
841       25u,
842       "שלום עולם\n)مرحبا بالعالم("
843     },
844     {
845       "Right to left characters with some characters to mirror. Update last paragraph.",
846       "שלום עולם\n(مرحبا بالعالم)",
847       10u,
848       15u,
849       "שלום עולם\n)مرحبا بالعالم("
850     },
851     {
852       "Mix of bidirectional text. With more paragraphs.",
853       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
854       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
855       0u,
856       239u,
857       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
858       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום )hello) world demo )עולם(\nשלום )مرحبا بالعالم עולם( )hello("
859     },
860     {
861       "Mix of bidirectional text. With more paragraphs. Update middle paragraphs.",
862       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
863       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
864       29u,
865       38u,
866       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
867       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"
868     },
869     {
870       "Mix of bidirectional text. With more paragraphs. Update middle paragraphs (2).",
871       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
872       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
873       67u,
874       100u,
875       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
876       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"
877     },
878   };
879   const unsigned int numberOfTests = 8u;
880
881   for( unsigned int index = 0u; index < numberOfTests; ++index )
882   {
883     ToolkitTestApplication application;
884     if( !GetMirroredTextTest( data[index] ) )
885     {
886       tet_result(TET_FAIL);
887     }
888   }
889
890   tet_result(TET_PASS);
891   END_TEST;
892 }
893
894 int UtcDaliGetCharactersDirection(void)
895 {
896   tet_infoline(" UtcDaliGetCharactersDirection");
897
898   bool directions01[] = {};
899   bool directions02[] = {
900     false, false, false, false, false, false, false, false, false, false,
901     false, false, false, false, false, false, false, false, false, false,
902     false, false, false, false, false, false, false, false };
903   bool directions03[] = {
904     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
905     true,  true,  true,  true,  true,  true,  true,  true,  true };
906   bool directions04[] = {
907     false, false, false, false, false, false, false, false, false, false,
908     false, false, false, false, false, false, false, false, false, false,
909     false, false, false, false, true,  true,  true,  true,  true,  true,
910     true,  true,  true,  false, true,  true,  true,  true,  true,  true,
911     true,  true,  true,  true,  false, false, false, false, false, false,
912     false, false, false, false, false };
913   bool directions05[] = {
914     false, false, false, false, false, false, false, false, false, false,
915     false, false, false, false, false, false, false, false, false, false,
916     false, false, false, false, false, false, false, false, false, false,
917     false, false, false, false, false, false, false, false, false, false,
918     false, true,  true,  true,  true,  true,  true,  true,  true,  true,
919     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
920     true,  true,  true,  true,  false, true,  true,  true,  true,  true,
921     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
922     true,  true,  true,  true,  true,  true,  true,  true,  true,  false,
923     false, false, false, false, true,  true,  true,  true,  true,  true,
924     true,  true,  true,  true,  true,  true,  true,  true,  true,  false,
925     false, false, false, false, true,  true,  true,  true,  true,  true,
926     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
927     true,  true,  true,  true,  true,  true,  true,  true,  true,  false,
928     false, false, false, false, false, false, false, false, false, false,
929     false, false, false, false, false, false, false, false, false, false,
930     false, false, true,  true,  true,  true,  true,  true,  true,  true,
931     true,  true,  true,  true,  true,  true,  false, false, false, false,
932     false, false, false, false, false, false, false, false, false, false,
933     false, false, true,  true,  true,  true,  true,  true,  true,  true,
934     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
935     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
936     true,  true,  false, false, false, false, false };
937
938     bool directions06[] = {
939     true,  true,  true,  true,  true,  true,  true,  true,  true, true,
940     false, false, false, false, false, false, false, false, false, false,
941     false, false, false, false, false, false };
942
943   struct GetCharactersDirectionData data[] =
944   {
945     {
946       "Zero characters",
947       "",
948       0u,
949       0u,
950       directions01,
951       false
952     },
953     {
954       "Left to right characters only",
955       "Hello world\nhello world demo",
956       0u,
957       28u,
958       directions02,
959       false
960     },
961     {
962       "Right to left characters only",
963       "שלום עולם\nשלום עולם",
964       0u,
965       19u,
966       directions03,
967       false
968     },
969     {
970       "Mix of bidirectional text",
971       "Hello world\nhello world שלום עולם\nשלום עולם hello world",
972       0u,
973       55u,
974       directions04,
975       false
976     },
977     {
978       "Mix of bidirectional text. With more paragraphs.",
979       "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
980       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
981       0u,
982       227u,
983       directions05,
984       false
985     },
986     {
987       "Mix of bidirectional text. With more paragraphs. Update first paragraph.",
988       "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
989       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
990       0u,
991       17u,
992       directions05,
993       false
994     },
995     {
996       "Mix of bidirectional text. With more paragraphs. Update from character 29",
997       "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
998       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
999       29u,
1000       134u,
1001       directions05,
1002       false
1003     },
1004     {
1005       "Mix of bidirectional text. With more paragraphs. Update from character 163",
1006       "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
1007       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
1008       163u,
1009       35u,
1010       directions05,
1011       false
1012     },
1013     {
1014       "Mix of bidirectional text. With brackets and LRM",
1015       "שלום עולם &lrm;(hello)[world]&lrm;",
1016       0u,
1017       26u,
1018       directions06,
1019       true
1020     }
1021   };
1022   const unsigned int numberOfTests = 9u;
1023
1024   for( unsigned int index = 0u; index < numberOfTests; ++index )
1025   {
1026     ToolkitTestApplication application;
1027     if( !GetCharactersDirectionTest( data[index] ) )
1028     {
1029       tet_result(TET_FAIL);
1030     }
1031   }
1032
1033   tet_result(TET_PASS);
1034   END_TEST;
1035 }