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