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