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