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