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