[dali_2.1.6] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-BidirectionalSupport.cpp
1 /*
2  * Copyright (c) 2021 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 // bool GetMirroredText( const Vector<Character>& text,
42 //                       Vector<CharacterDirection>& directions,
43 //                       const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
44 //                       CharacterIndex startIndex,
45 //                       Length numberOfCharacters,
46 //                       Vector<Character>& mirroredText )
47 // void GetCharactersDirection( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
48 //                              Length totalNumberOfCharacters,
49 //                              CharacterIndex startIndex,
50 //                              Length numberOfCharacters,
51 //                              Vector<CharacterDirection>& directions )
52
53 //////////////////////////////////////////////////////////
54
55 namespace
56 {
57
58 struct SetBidirectionalInfoData
59 {
60   std::string   description;                 ///< Description of the test.
61   std::string   text;                        ///< Input text.
62   unsigned int  startIndex;                  ///< The index from where the model is updated.
63   unsigned int  numberOfCharacters;          ///< The number of characters to update.
64   unsigned int  numberOfParagraphs;          ///< The expected number of bidirectional paragraphs.
65   unsigned int* indices;                     ///< The expected indices to the first character of each paragraph.
66   unsigned int* numberOfParagraphCharacters; ///< The expected number of characters of each paragraph.
67   bool*         directions;                  ///< The expected direction of each paragraph.
68 };
69
70 struct BidiLineData
71 {
72   unsigned int  characterIndex;
73   unsigned int  numberOfCharacters;
74   unsigned int* visualToLogical;
75 };
76
77 struct GetMirroredTextData
78 {
79   std::string  description;        ///< Description of the test.
80   std::string  text;               ///< Input text.
81   unsigned int startIndex;         ///< The index from where the model is updated.
82   unsigned int numberOfCharacters; ///< The number of the characters.
83   std::string  mirroredText;       ///< The expected result.
84 };
85
86 struct GetCharactersDirectionData
87 {
88   std::string  description;            ///< Description of the test.
89   std::string  text;                   ///< Input text.
90   unsigned int startIndex;             ///< The index from where the model is updated.
91   unsigned int numberOfCharacters;     ///< The number of characters.
92   bool*        directions;             ///< The expected directions.
93   bool         markupProcessorEnabled; ///< Enable markup processor to use markup text.
94 };
95
96 bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
97 {
98   // 1) Create the model.
99   ModelPtr textModel;
100   MetricsPtr metrics;
101   Size textArea(100.f, 60.f);
102   Size layoutSize;
103
104   // Create the model.
105   const Vector<FontDescriptionRun> fontDescriptions;
106   const LayoutOptions options;
107   CreateTextModel( data.text,
108                    textArea,
109                    fontDescriptions,
110                    options,
111                    layoutSize,
112                    textModel,
113                    metrics,
114                    false,
115                    LineWrap::WORD,
116                    false,
117                    Toolkit::DevelText::EllipsisPosition::END,
118                    0.f );
119
120   LogicalModelPtr logicalModel = textModel->mLogicalModel;
121   VisualModelPtr visualModel = textModel->mVisualModel;
122
123   // 2) Clear the bidirectional paragraph info data.
124   Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
125   if( 0u != data.numberOfCharacters )
126   {
127     ClearCharacterRuns( data.startIndex,
128                         data.startIndex + data.numberOfCharacters - 1u,
129                         bidirectionalInfo );
130   }
131
132   // 3) Call the SetBidirectionalInfo() function.
133   SetBidirectionalInfo( logicalModel->mText,
134                         logicalModel->mScriptRuns,
135                         logicalModel->mLineBreakInfo,
136                         data.startIndex,
137                         data.numberOfCharacters,
138                         bidirectionalInfo );
139
140   // 4) Compare with the expected results.
141   TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
142
143   if( data.numberOfParagraphs != bidirectionalInfo.Count() )
144   {
145     // Different number of expected bidirectional paragraphs.
146     std::cout << "  Different number of bidi paragraphs : " << bidirectionalInfo.Count() << ", expected : " << data.numberOfParagraphs << std::endl;
147     return false;
148   }
149
150   for( unsigned int index = 0u; index < data.numberOfParagraphs; ++index )
151   {
152     const BidirectionalParagraphInfoRun& run = bidirectionalInfo[index];
153
154     const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection( run.bidirectionalInfoIndex );
155     if( direction != data.directions[index] )
156     {
157       std::cout << "  Different direction" << std::endl;
158       std::cout << "        paragraph : " << index << std::endl;
159       std::cout << "            index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
160       std::cout << "  expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
161       return false;
162     }
163
164     if( run.characterRun.characterIndex != data.indices[index] )
165     {
166       std::cout << "  Different index" << 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     if( run.characterRun.numberOfCharacters != data.numberOfParagraphCharacters[index] )
173     {
174       std::cout << "  Different number of characters" << std::endl;
175       std::cout << "        paragraph : " << index << std::endl;
176       std::cout << "            index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
177       std::cout << "  expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
178       return false;
179     }
180   }
181
182   return true;
183 }
184
185 bool GetMirroredTextTest( const GetMirroredTextData& data )
186 {
187   // 1) Create the model.
188   ModelPtr textModel;
189   MetricsPtr metrics;
190   Size textArea(100.f, 60.f);
191   Size layoutSize;
192
193   // Create the model.
194   const Vector<FontDescriptionRun> fontDescriptions;
195   const LayoutOptions options;
196   CreateTextModel( data.text,
197                    textArea,
198                    fontDescriptions,
199                    options,
200                    layoutSize,
201                    textModel,
202                    metrics,
203                    false,
204                    LineWrap::WORD,
205                    false,
206                    Toolkit::DevelText::EllipsisPosition::END,
207                    0.f );
208
209   LogicalModelPtr logicalModel = textModel->mLogicalModel;
210   VisualModelPtr visualModel = textModel->mVisualModel;
211
212   // 2) Call the GetMirroredText() function for the whole text
213   Vector<Character> mirroredText;
214   bool mirrored = false;
215   mirrored = GetMirroredText( logicalModel->mText,
216                               logicalModel->mCharacterDirections,
217                               logicalModel->mBidirectionalParagraphInfo,
218                               0u,
219                               logicalModel->mText.Count(),
220                               mirroredText );
221
222   // 3) Call the GetMirroredText() function for the given index + number of characters
223   mirrored = GetMirroredText( logicalModel->mText,
224                               logicalModel->mCharacterDirections,
225                               logicalModel->mBidirectionalParagraphInfo,
226                               data.startIndex,
227                               data.numberOfCharacters,
228                               mirroredText );
229
230   // 4) Compare the results.
231
232   // Convert to utf8
233   std::string mirroredString;
234   Utf32ToUtf8( mirroredText.Begin(),
235                mirroredText.Count(),
236                mirroredString );
237
238   if( !mirrored && ( mirroredString != data.text ) )
239   {
240     std::cout << "  No mirrored text and mirroredString != data.text." << std::endl;
241     std::cout << "  mirrored string : [" << mirroredString << "]" << std::endl;
242     std::cout << "             text : [" << data.text << "]" << std::endl;
243     return false;
244   }
245
246   if( mirrored && ( mirroredString == data.text ) )
247   {
248     std::cout << "  Mirrored text and mirroredString == data.text." << std::endl;
249     std::cout << "  mirrored string : [" << mirroredString << "]" << std::endl;
250     std::cout << "             text : [" << data.text << "]" << std::endl;
251     return false;
252   }
253
254   if( mirrored && ( mirroredString != data.mirroredText ) )
255   {
256     std::cout << "  Mirrored text and mirroredString != data.mirroredText." << std::endl;
257     std::cout << "  mirrored string : [" << mirroredString << "]" << std::endl;
258     std::cout << "             text : [" << data.mirroredText << "]" << std::endl;
259     return false;
260   }
261
262   return true;
263 }
264
265 bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
266 {
267   // 1) Create the model.
268   ModelPtr textModel;
269   MetricsPtr metrics;
270   Size textArea(100.f, 60.f);
271   Size layoutSize;
272
273   // Create the model.
274   const Vector<FontDescriptionRun> fontDescriptions;
275   const LayoutOptions options;
276   CreateTextModel( data.text,
277                    textArea,
278                    fontDescriptions,
279                    options,
280                    layoutSize,
281                    textModel,
282                    metrics,
283                    data.markupProcessorEnabled,
284                    LineWrap::WORD,
285                    false,
286                    Toolkit::DevelText::EllipsisPosition::END,
287                    0.f );
288
289   LogicalModelPtr logicalModel = textModel->mLogicalModel;
290   VisualModelPtr visualModel = textModel->mVisualModel;
291
292   Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
293
294   // 2) Clear the direction info data.
295   Vector<CharacterDirection>& directions = logicalModel->mCharacterDirections;
296
297   if( directions.Count() >= data.startIndex + data.numberOfCharacters )
298   {
299     directions.Erase( directions.Begin() + data.startIndex,
300                       directions.Begin() + data.startIndex + data.numberOfCharacters );
301   }
302
303   // 3) Call GetCharactersDirection() function.
304
305   GetCharactersDirection( bidirectionalInfo,
306                           logicalModel->mText.Count(),
307                           data.startIndex,
308                           data.numberOfCharacters,
309                           directions );
310
311   for( unsigned int index = 0u; index < logicalModel->mText.Count(); ++index )
312   {
313     if( data.directions[index] != directions[index] )
314     {
315       return false;
316     }
317   }
318
319   return true;
320 }
321
322 } // namespace
323
324 //////////////////////////////////////////////////////////
325
326 int UtcDaliSetBidirectionalInfo(void)
327 {
328   tet_infoline(" UtcDaliSetBidirectionalInfo");
329
330   unsigned int indices01[] = {};
331   unsigned int numberOfCharacters01[] = {};
332   bool         direction01[] = {};
333   unsigned int indices02[] = {};
334   unsigned int numberOfCharacters02[] = {};
335   bool         direction02[] = {};
336   unsigned int indices03[] = { 17u, 48u };
337   unsigned int numberOfCharacters03[] = { 14u, 14u };
338   bool         direction03[] = { true, true };
339   unsigned int indices04[] = { 17u, 31u, 79u };
340   unsigned int numberOfCharacters04[] = { 14u, 48u, 31u };
341   bool         direction04[] = { true, false, true };
342   unsigned int indices05[] = { 17u, 41u, 117u };
343   unsigned int numberOfCharacters05[] = { 24u, 76u, 49u };
344   bool         direction05[] = { true, false, true };
345   unsigned int indices06[] = { 17u, 48u };
346   unsigned int numberOfCharacters06[] = { 14u, 14u };
347   bool         direction06[] = { true, true };
348   unsigned int indices07[] = { 17u, 31u, 79u };
349   unsigned int numberOfCharacters07[] = { 14u, 48u, 31u };
350   bool         direction07[] = { true, false, true };
351   unsigned int indices08[] = { 17u, 41u, 117u };
352   unsigned int numberOfCharacters08[] = { 24u, 76u, 49u };
353   bool         direction08[] = { true, false, true };
354
355   struct SetBidirectionalInfoData data[] =
356   {
357     {
358       "Zero characters",
359       "",
360       0u,
361       0u,
362       0u,
363       indices01,
364       numberOfCharacters01,
365       direction01
366     },
367     {
368       "Some left to right paragraphs",
369       "Hello world\ndemo\n\n",
370       0u,
371       18u,
372       0u,
373       indices02,
374       numberOfCharacters02,
375       direction02
376     },
377     {
378       "A mix of left to right and right to left paragraphs.",
379       "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
380       0u,
381       78u,
382       2u,
383       indices03,
384       numberOfCharacters03,
385       direction03
386     },
387     {
388       "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
389       "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
390       0u,
391       126u,
392       3u,
393       indices04,
394       numberOfCharacters04,
395       direction04
396     },
397     {
398       "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.",
399       "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
400       0u,
401       182u,
402       3u,
403       indices05,
404       numberOfCharacters05,
405       direction05
406     },
407     {
408       "A mix of left to right and right to left paragraphs. Updates a left to right paragraph.",
409       "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
410       31u,
411       17u,
412       2u,
413       indices06,
414       numberOfCharacters06,
415       direction06
416     },
417     {
418       "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
419       "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
420       0u,
421       126u,
422       3u,
423       indices07,
424       numberOfCharacters07,
425       direction07
426     },
427     {
428       "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.",
429       "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
430       0u,
431       41u,
432       3u,
433       indices08,
434       numberOfCharacters08,
435       direction08
436     },
437     {
438       "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.",
439       "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
440       41u,
441       76u,
442       3u,
443       indices08,
444       numberOfCharacters08,
445       direction08
446     },
447     {
448       "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",
449       "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
450       117u,
451       65u,
452       3u,
453       indices08,
454       numberOfCharacters08,
455       direction08
456     },
457   };
458   const unsigned int numberOfTests = 10u;
459
460   for( unsigned int index = 0u; index < numberOfTests; ++index )
461   {
462     ToolkitTestApplication application;
463     if( !SetBidirectionalInfoTest( data[index] ) )
464     {
465       tet_result(TET_FAIL);
466     }
467   }
468
469   tet_result(TET_PASS);
470   END_TEST;
471 }
472
473 int UtcDaliGetMirroredText(void)
474 {
475   tet_infoline(" UtcDaliGetMirroredText");
476
477   struct GetMirroredTextData data[] =
478   {
479     {
480       "Zero characters.",
481       "",
482       0u,
483       0u,
484       ""
485     },
486     {
487       "Left to right characters only.",
488       "Hello world\nhello world demo.",
489       0u,
490       29u,
491       "Hello world\nhello world demo."
492     },
493     {
494       "Right to left characters but with no characters to mirror.",
495       "שלום עולם\nمرحبا بالعالم",
496       0u,
497       23u,
498       "שלום עולם\nمرحبا بالعالم"
499     },
500     {
501       "Right to left characters with some characters to mirror.",
502       "שלום עולם\n(مرحبا بالعالم)",
503       0u,
504       25u,
505       "שלום עולם\n)مرحبا بالعالم("
506     },
507     {
508       "Right to left characters with some characters to mirror. Update last paragraph.",
509       "שלום עולם\n(مرحبا بالعالم)",
510       10u,
511       15u,
512       "שלום עולם\n)مرحبا بالعالم("
513     },
514     {
515       "Mix of bidirectional text. With more paragraphs.",
516       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
517       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
518       0u,
519       239u,
520       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
521       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום )hello) world demo )עולם(\nשלום )مرحبا بالعالم עולם( )hello("
522     },
523     {
524       "Mix of bidirectional text. With more paragraphs. Update middle paragraphs.",
525       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
526       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
527       29u,
528       38u,
529       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
530       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"
531     },
532     {
533       "Mix of bidirectional text. With more paragraphs. Update middle paragraphs (2).",
534       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
535       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
536       67u,
537       100u,
538       "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
539       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"
540     },
541   };
542   const unsigned int numberOfTests = 8u;
543
544   for( unsigned int index = 0u; index < numberOfTests; ++index )
545   {
546     ToolkitTestApplication application;
547     if( !GetMirroredTextTest( data[index] ) )
548     {
549       tet_result(TET_FAIL);
550     }
551   }
552
553   tet_result(TET_PASS);
554   END_TEST;
555 }
556
557 int UtcDaliGetCharactersDirection(void)
558 {
559   tet_infoline(" UtcDaliGetCharactersDirection");
560
561   bool directions01[] = {};
562   bool directions02[] = {
563     false, false, false, false, false, false, false, false, false, false,
564     false, false, false, false, false, false, false, false, false, false,
565     false, false, false, false, false, false, false, false };
566   bool directions03[] = {
567     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
568     true,  true,  true,  true,  true,  true,  true,  true,  true };
569   bool directions04[] = {
570     false, false, false, false, false, false, false, false, false, false,
571     false, false, false, false, false, false, false, false, false, false,
572     false, false, false, false, true,  true,  true,  true,  true,  true,
573     true,  true,  true,  false, true,  true,  true,  true,  true,  true,
574     true,  true,  true,  true,  false, false, false, false, false, false,
575     false, false, false, false, false };
576   bool directions05[] = {
577     false, false, false, false, false, false, false, false, false, false,
578     false, false, false, false, false, false, false, false, false, false,
579     false, false, false, false, false, false, false, false, false, false,
580     false, false, false, false, false, false, false, false, false, false,
581     false, true,  true,  true,  true,  true,  true,  true,  true,  true,
582     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
583     true,  true,  true,  true,  false, true,  true,  true,  true,  true,
584     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
585     true,  true,  true,  true,  true,  true,  true,  true,  true,  false,
586     false, false, false, false, true,  true,  true,  true,  true,  true,
587     true,  true,  true,  true,  true,  true,  true,  true,  true,  false,
588     false, false, false, false, true,  true,  true,  true,  true,  true,
589     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
590     true,  true,  true,  true,  true,  true,  true,  true,  true,  false,
591     false, false, false, false, false, false, false, false, false, false,
592     false, false, false, false, false, false, false, false, false, false,
593     false, false, true,  true,  true,  true,  true,  true,  true,  true,
594     true,  true,  true,  true,  true,  true,  false, false, false, false,
595     false, false, false, false, false, false, false, false, false, false,
596     false, false, true,  true,  true,  true,  true,  true,  true,  true,
597     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
598     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
599     true,  true,  false, false, false, false, false };
600
601     bool directions06[] = {
602     true,  true,  true,  true,  true,  true,  true,  true,  true, true,
603     false, false, false, false, false, false, false, false, false, false,
604     false, false, false, false, false, false };
605
606   struct GetCharactersDirectionData data[] =
607   {
608     {
609       "Zero characters",
610       "",
611       0u,
612       0u,
613       directions01,
614       false
615     },
616     {
617       "Left to right characters only",
618       "Hello world\nhello world demo",
619       0u,
620       28u,
621       directions02,
622       false
623     },
624     {
625       "Right to left characters only",
626       "שלום עולם\nשלום עולם",
627       0u,
628       19u,
629       directions03,
630       false
631     },
632     {
633       "Mix of bidirectional text",
634       "Hello world\nhello world שלום עולם\nשלום עולם hello world",
635       0u,
636       55u,
637       directions04,
638       false
639     },
640     {
641       "Mix of bidirectional text. With more paragraphs.",
642       "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
643       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
644       0u,
645       227u,
646       directions05,
647       false
648     },
649     {
650       "Mix of bidirectional text. With more paragraphs. Update first paragraph.",
651       "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
652       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
653       0u,
654       17u,
655       directions05,
656       false
657     },
658     {
659       "Mix of bidirectional text. With more paragraphs. Update from character 29",
660       "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
661       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
662       29u,
663       134u,
664       directions05,
665       false
666     },
667     {
668       "Mix of bidirectional text. With more paragraphs. Update from character 163",
669       "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
670       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
671       163u,
672       35u,
673       directions05,
674       false
675     },
676     {
677       "Mix of bidirectional text. With brackets and LRM",
678       "שלום עולם &lrm;(hello)[world]&lrm;",
679       0u,
680       26u,
681       directions06,
682       true
683     }
684   };
685   const unsigned int numberOfTests = 9u;
686
687   for( unsigned int index = 0u; index < numberOfTests; ++index )
688   {
689     ToolkitTestApplication application;
690     if( !GetCharactersDirectionTest( data[index] ) )
691     {
692       tet_result(TET_FAIL);
693     }
694   }
695
696   tet_result(TET_PASS);
697   END_TEST;
698 }