Merge "Fix for UtcDaliGetLogicalCursorIndex" into devel/master
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-LogicalModel.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 #include <unistd.h>
21
22 #include <dali-toolkit-test-suite-utils.h>
23 #include <dali-toolkit/internal/text/text-run-container.h>
24 #include <dali-toolkit/dali-toolkit.h>
25 #include <toolkit-text-utils.h>
26
27
28 using namespace Dali;
29 using namespace Toolkit;
30 using namespace Text;
31
32 // Tests the following functions.
33 //
34 // void CreateParagraphInfo( CharacterIndex startIndex,
35 //                           Length numberOfCharacters );
36 // void FindParagraphs( CharacterIndex index,
37 //                      Length numberOfCharacters,
38 //                      Vector<ParagraphRunIndex>& paragraphs );
39 // bool FetchBidirectionalLineInfo( CharacterIndex characterIndex )
40 // CharacterIndex GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const;
41 // CharacterIndex GetLogicalCursorIndex( CharacterIndex visualCursorIndex ) const;
42
43 //////////////////////////////////////////////////////////
44
45 namespace
46 {
47 const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
48
49 struct CreateParagraphData
50 {
51   std::string    description;                    ///< Description of the test.
52   std::string    text;                           ///< Input text.
53   CharacterIndex index;                          ///< The first character index.
54   Length         numberOfCharacters;             ///< The number of characters.
55   unsigned int   numberOfParagraphs;             ///< The expected number of paragraphs.
56   unsigned int*  indices;                        ///< The expected paragraph info indices.
57   unsigned int*  numberOfCharactersPerParagraph; ///< The expected number of characters of each paragraph.
58 };
59
60 struct FindParagraphData
61 {
62   std::string    description;        ///< Description of the test.
63   std::string    text;               ///< Input text.
64   CharacterIndex index;              ///< The first character index.
65   Length         numberOfCharacters; ///< The number of characters.
66   unsigned int   numberOfParagraphs; ///< The expected number of paragraphs.
67   unsigned int*  paragraphs;         ///< The expected paragraph info.
68 };
69
70 struct FetchBidirectionalLineInfoData
71 {
72   std::string   description;    ///< Description of the test.
73   std::string   text;           ///< Input text.
74   unsigned int  numberOfTests;  ///< The number of tests.
75   unsigned int* characterIndex; ///< The logical character index.
76   bool*         fetched;        ///< Whether the expected bidi line exists.
77   unsigned int* bidiLineIndex;  ///< Index to the expected bidi line.
78 };
79
80 struct GetLogicalCharacterIndexData
81 {
82   std::string   description;        ///< Description of the test.
83   std::string   text;               ///< Input text.
84   Size          textArea;           ///< The text area.
85   unsigned int  numberOfIndices;    ///< The number of characters to set.
86   unsigned int* visualToLogical;    ///< The expected visual to logical conversion table.
87   unsigned int* cachedBidiLine;     ///< The cached bidi line index for each character.
88 };
89
90 struct GetLogicalCursorIndexData
91 {
92   std::string         description;        ///< Description of the test.
93   std::string         text;               ///< Input text.
94   Size                textArea;           ///< The text area.
95   unsigned int        numberOfFonts;      ///< The number of fonts.
96   FontDescriptionRun* fontDescriptions;   ///< The font descriptions.
97   unsigned int        numberOfIndices;    ///< The number of characters to set.
98   unsigned int*       visualCursorIndex;  ///< The given cursor visual index.
99   unsigned int*       characterIndex;     ///< Index to the first logical character of the line.
100   unsigned int*       logicalCursorIndex; ///< The expected cursor logical index.
101   unsigned int*       cachedBidiLine;     ///< The cached bidi line index for each character.
102 };
103
104 bool CreateParagraphTest( const CreateParagraphData& data )
105 {
106   // 1) Create the model.
107   LogicalModelPtr logicalModel;
108   VisualModelPtr visualModel;
109   MetricsPtr metrics;
110   Size textArea(100.f, 60.f);
111   Size layoutSize;
112
113   Vector<FontDescriptionRun> fontDescriptionRuns;
114   LayoutOptions options;
115   CreateTextModel( data.text,
116                    textArea,
117                    fontDescriptionRuns,
118                    options,
119                    layoutSize,
120                    logicalModel,
121                    visualModel,
122                    metrics,
123                    false );
124
125   // 2) Clear the paragraphs.
126   Vector<ParagraphRun>& paragraphs = logicalModel->mParagraphInfo;
127   ClearCharacterRuns( data.index,
128                       data.index + data.numberOfCharacters - 1u,
129                       paragraphs );
130
131   // 3) Call the LogicalModel::CreateParagraphInfo() method
132   logicalModel->CreateParagraphInfo( data.index,
133                                      data.numberOfCharacters );
134
135   // 4) Compare the results.
136   if( data.numberOfParagraphs != paragraphs.Count() )
137   {
138     std::cout << "  Different number of paragraphs : " << paragraphs.Count() << ", expected : " << data.numberOfParagraphs << std::endl;
139     return false;
140   }
141
142   unsigned int index = 0u;
143   for( Vector<ParagraphRun>::ConstIterator it = paragraphs.Begin(),
144          endIt = paragraphs.End();
145        it != endIt;
146        ++it, ++index )
147   {
148     const ParagraphRun& paragraph( *it );
149
150     if( data.indices[index] != paragraph.characterRun.characterIndex )
151     {
152       std::cout << "  Different character index for paragraph : " << index << ", " << paragraph.characterRun.characterIndex << ", expected : " << data.indices[index] << std::endl;
153       return false;
154     }
155     if( data.numberOfCharactersPerParagraph[index] != paragraph.characterRun.numberOfCharacters )
156     {
157       std::cout << "  Different number of characters for paragraph : " << index << ", " << paragraph.characterRun.numberOfCharacters << ", expected : " << data.numberOfCharactersPerParagraph[index] << std::endl;
158       return false;
159     }
160   }
161
162   return true;
163 }
164
165 bool FindParagraphTest( const FindParagraphData& data )
166 {
167   // 1) Create the model.
168   LogicalModelPtr logicalModel;
169   VisualModelPtr visualModel;
170   MetricsPtr metrics;
171   Size textArea(100.f, 60.f);
172   Size layoutSize;
173
174   Vector<FontDescriptionRun> fontDescriptionRuns;
175   LayoutOptions options;
176   CreateTextModel( data.text,
177                    textArea,
178                    fontDescriptionRuns,
179                    options,
180                    layoutSize,
181                    logicalModel,
182                    visualModel,
183                    metrics,
184                    false );
185
186   // 2) Find the paragraphs.
187   Vector<ParagraphRunIndex> paragraphs;
188   logicalModel->FindParagraphs( data.index, data.numberOfCharacters, paragraphs );
189
190   // 3) compare the results.
191   if( data.numberOfParagraphs != paragraphs.Count() )
192   {
193     return false;
194   }
195
196   unsigned int index = 0u;
197   for( Vector<ParagraphRunIndex>::ConstIterator it = paragraphs.Begin(),
198          endIt = paragraphs.End();
199        it != endIt;
200        ++it, ++index )
201   {
202     const ParagraphRunIndex paragraphIndex = *it;
203
204     if( paragraphIndex != data.paragraphs[index] )
205     {
206       return false;
207     }
208   }
209
210   return true;
211 }
212
213 bool FetchBidirectionalLineInfoTest( const FetchBidirectionalLineInfoData& data )
214 {
215   std::cout << "  testing : " << data.description << std::endl;
216   // Create the model.
217   LogicalModelPtr logicalModel;
218   VisualModelPtr visualModel;
219   MetricsPtr metrics;
220   Size textArea( 100.f, 300.f );
221   Size layoutSize;
222
223   // Create the model with the whole text.
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                    metrics,
234                    false );
235
236   for( unsigned int index = 0; index < data.numberOfTests; ++index )
237   {
238     const bool fetched = logicalModel->FetchBidirectionalLineInfo( data.characterIndex[index] );
239
240     if( fetched != data.fetched[index] )
241     {
242       std::cout << "  Different fetched result : " << fetched << ", expected : " << data.fetched[index] << std::endl;
243       return false;
244     }
245
246     if( fetched )
247     {
248       if( logicalModel->mBidirectionalLineIndex != data.bidiLineIndex[index] )
249       {
250         std::cout << "  Different bidi line index : " << logicalModel->mBidirectionalLineIndex << ", expected : " << data.bidiLineIndex << std::endl;
251         return false;
252       }
253     }
254   }
255
256   return true;
257 }
258
259 bool GetLogicalCharacterIndexTest( const GetLogicalCharacterIndexData& data )
260 {
261   std::cout << "  testing : " << data.description << std::endl;
262   // Create the model.
263   LogicalModelPtr logicalModel;
264   VisualModelPtr visualModel;
265   MetricsPtr metrics;
266   Size layoutSize;
267
268   // Create the model with the whole text.
269   const Vector<FontDescriptionRun> fontDescriptions;
270   const LayoutOptions options;
271   CreateTextModel( data.text,
272                    data.textArea,
273                    fontDescriptions,
274                    options,
275                    layoutSize,
276                    logicalModel,
277                    visualModel,
278                    metrics,
279                    false );
280
281   for( unsigned int index = 0u; index < data.numberOfIndices; ++index )
282   {
283     // Check the current cached bidi line index. (Check it before call the GetLogicalCharacterIndex() method )
284     if( data.cachedBidiLine[index] != logicalModel->mBidirectionalLineIndex )
285     {
286       std::cout << "  index : " << index << ", different cached bidi index : " << logicalModel->mBidirectionalLineIndex << ", expected : " << data.cachedBidiLine[index] << std::endl;
287       return false;
288     }
289
290     const bool fetched = logicalModel->FetchBidirectionalLineInfo( index );
291     const Character logicalIndex = fetched ? logicalModel->GetLogicalCharacterIndex( index ) : index;
292
293     if( data.visualToLogical[index] != logicalIndex )
294     {
295       std::cout << "  visual index : " << index << ", different logical index : " << logicalIndex << ", expected : " << data.visualToLogical[index] << std::endl;
296       return false;
297     }
298   }
299   return true;
300 }
301
302 bool GetLogicalCursorIndexTest( const GetLogicalCursorIndexData& data )
303 {
304   tet_printf( "  testing : %s\n", data.description.c_str() );
305
306   // Load some fonts.
307   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
308   fontClient.SetDpi( 96u, 96u );
309
310   char* pathNamePtr = get_current_dir_name();
311   const std::string pathName( pathNamePtr );
312   free( pathNamePtr );
313
314   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" );
315   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" );
316
317   // Create the model.
318   LogicalModelPtr logicalModel;
319   VisualModelPtr visualModel;
320   MetricsPtr metrics;
321   Size layoutSize;
322
323   // Create the model with the whole text.
324   Vector<FontDescriptionRun> fontDescriptionRuns;
325   if( 0u != data.numberOfFonts )
326   {
327     fontDescriptionRuns.Insert( fontDescriptionRuns.End(),
328                                 data.fontDescriptions,
329                                 data.fontDescriptions + data.numberOfFonts );
330   }
331
332   const LayoutOptions options;
333   CreateTextModel( data.text,
334                    data.textArea,
335                    fontDescriptionRuns,
336                    options,
337                    layoutSize,
338                    logicalModel,
339                    visualModel,
340                    metrics,
341                    false );
342
343   for( unsigned int index = 0u; index < data.numberOfIndices; ++index )
344   {
345     const bool fetched = logicalModel->FetchBidirectionalLineInfo( data.characterIndex[index] );
346     tet_printf("  fetched %d, line index %d, expected line index %d\n", fetched, logicalModel->mBidirectionalLineIndex, data.cachedBidiLine[index] );
347
348     if( logicalModel->mBidirectionalLineIndex != data.cachedBidiLine[index] )
349     {
350       tet_printf( "  test : %d, different cached line index : %d, expected : %d\n", index, logicalModel->mBidirectionalLineIndex, data.cachedBidiLine[index] );
351       return false;
352     }
353
354     const CharacterIndex visualCharacterIndex = data.visualCursorIndex[index];
355     const CharacterIndex logicalCursorIndex = fetched ? logicalModel->GetLogicalCursorIndex( visualCharacterIndex ) : visualCharacterIndex;
356     tet_printf("  visual index %d, logical index %d\n", visualCharacterIndex, logicalCursorIndex);
357
358     if( logicalCursorIndex != data.logicalCursorIndex[index] )
359     {
360       tet_printf( "  test : %d, visual index : %d, different logical cursor index :%d, expected : %d\n", index, visualCharacterIndex, logicalCursorIndex, data.logicalCursorIndex[index] );
361       return false;
362     }
363   }
364
365   return true;
366 }
367
368 } // namespace
369
370 //////////////////////////////////////////////////////////
371 //
372 // UtcDaliCreateParagraph
373 // UtcDaliFindParagraph
374 // UtcDaliFetchBidirectionalLineInfo
375 // UtcDaliGetLogicalCharacterIndex
376 // UtcDaliGetLogicalCursorIndex
377 //
378 //////////////////////////////////////////////////////////
379
380 int UtcDaliCreateParagraph(void)
381 {
382   tet_infoline(" UtcDaliCreateParagraph");
383
384   unsigned int paragraphsIndices01[] = { 0u };
385   unsigned int paragraphsNumberOfCharacters01[] = { 0u };
386   unsigned int paragraphsIndices02[] = { 0u, 12u, 17u };
387   unsigned int paragraphsNumberOfCharacters02[] = { 12u, 5u, 1u };
388   unsigned int paragraphsIndices03[] = { 0u, 12u, 17u, 34u };
389   unsigned int paragraphsNumberOfCharacters03[] = { 12u, 5u, 17u ,1u };
390
391   struct CreateParagraphData data[] =
392   {
393     {
394       "Zero characters",
395       "",
396       0u,
397       0u,
398       0u,
399       paragraphsIndices01,
400       paragraphsNumberOfCharacters01,
401     },
402     {
403       "Some paragraphs",
404       "Hello world\ndemo\n\n",
405       0u,
406       18u,
407       3u,
408       paragraphsIndices02,
409       paragraphsNumberOfCharacters02,
410     },
411     {
412       "Some paragraphs. Update the initial paragraphs.",
413       "Hello world\ndemo\nhello world demo\n\n",
414       0u,
415       17u,
416       4u,
417       paragraphsIndices03,
418       paragraphsNumberOfCharacters03,
419     },
420     {
421       "Some paragraphs. Update the mid paragraphs.",
422       "Hello world\ndemo\nhello world demo\n\n",
423       12u,
424       5u,
425       4u,
426       paragraphsIndices03,
427       paragraphsNumberOfCharacters03,
428     },
429     {
430       "Some paragraphs. Update the final paragraphs.",
431       "Hello world\ndemo\nhello world demo\n\n",
432       17u,
433       18u,
434       4u,
435       paragraphsIndices03,
436       paragraphsNumberOfCharacters03,
437     },
438   };
439   const unsigned int numberOfTests = 5u;
440
441   for( unsigned int index = 0u; index < numberOfTests; ++index )
442   {
443     ToolkitTestApplication application;
444     if( !CreateParagraphTest( data[index] ) )
445     {
446       tet_result(TET_FAIL);
447     }
448   }
449
450   tet_result(TET_PASS);
451   END_TEST;
452 }
453
454 int UtcDaliFindParagraph(void)
455 {
456   tet_infoline(" UtcDaliFindParagraph");
457
458   unsigned int paragraphs01[] = {};
459   unsigned int paragraphs02[] = { 0u, 1u, 2u };
460   unsigned int paragraphs03[] = { 0u };
461   unsigned int paragraphs04[] = { 1u };
462   unsigned int paragraphs05[] = { 0u, 1u, 2u };
463
464   struct FindParagraphData data[] =
465   {
466     {
467       "Zero characters",
468       "",
469       0u,
470       100u,
471       0u,
472       paragraphs01,
473     },
474     {
475       "Some paragraphs",
476       "Hello world\ndemo\n\n",
477       0u,
478       18u,
479       3u,
480       paragraphs02
481     },
482     {
483       "Some paragraphs",
484       "Hello world\ndemo\n\n",
485       0u,
486       12u,
487       1u,
488       paragraphs03
489     },
490     {
491       "Some paragraphs",
492       "Hello world\ndemo\n\n",
493       12u,
494       5u,
495       1u,
496       paragraphs04
497     },
498     {
499       "Some paragraphs",
500       "Hello world\ndemo\n\n",
501       3u,
502       15u,
503       3u,
504       paragraphs05
505     },
506   };
507   const unsigned int numberOfTests = 5u;
508
509   for( unsigned int index = 0u; index < numberOfTests; ++index )
510   {
511     ToolkitTestApplication application;
512     if( !FindParagraphTest( data[index] ) )
513     {
514       tet_result(TET_FAIL);
515     }
516   }
517
518   tet_result(TET_PASS);
519   END_TEST;
520 }
521
522 int UtcDaliFetchBidirectionalLineInfo(void)
523 {
524   tet_infoline(" UtcDaliFetchBidirectionalLineInfo");
525
526   unsigned int logicalIndex01[] = { 0u };
527   bool fetched01[] = { false };
528   unsigned int bidiLine01[] = { 0u };
529
530   unsigned int logicalIndex02[] = { 3u };
531   bool fetched02[] = { false };
532   unsigned int bidiLine02[] = { 0u };
533
534   unsigned int logicalIndex03[] = { 0u, 11u, 12u, 21u, 22u, 33u, 34u, 43u, 44u, 54u};
535   bool fetched03[] = { false, false, true, true, false, false, true, true, false, false };
536   unsigned int bidiLine03[] = { 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 0u, 0u };
537
538   struct FetchBidirectionalLineInfoData data[] =
539   {
540     {
541       "Void text",
542       "",
543       1u,
544       logicalIndex01,
545       fetched01,
546       bidiLine01
547     },
548     {
549       "LTR text",
550       "Hello world",
551       1u,
552       logicalIndex02,
553       fetched02,
554       bidiLine02
555     },
556     {
557       "Bidi text",
558       "Hello world\nשלום עולם\nhello world\nשלום עולם\nhello world",
559       10u,
560       logicalIndex03,
561       fetched03,
562       bidiLine03
563     }
564   };
565   const unsigned int numberOfTests = 3u;
566
567   for( unsigned int index = 0u; index < numberOfTests; ++index )
568   {
569     ToolkitTestApplication application;
570     if( !FetchBidirectionalLineInfoTest( data[index] ) )
571     {
572       tet_result(TET_FAIL);
573     }
574   }
575
576   tet_result(TET_PASS);
577   END_TEST;
578 }
579
580 int UtcDaliGetLogicalCharacterIndex(void)
581 {
582   tet_infoline(" UtcDaliSetVisualToLogicalMap");
583
584   unsigned int visualToLogical01[] = {};
585   unsigned int  cachedBidiLine01[] = {};
586   unsigned int visualToLogical02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
587   unsigned int  cachedBidiLine02[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,  0u };
588   unsigned int visualToLogical03[] = { 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
589   unsigned int  cachedBidiLine03[] = {  0u,  0u,  0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u };
590
591   unsigned int visualToLogical04[] = { 0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
592   unsigned int  cachedBidiLine04[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
593                                        0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
594                                        1u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u };
595
596 // size 300, 300
597 // LO   H  e  l  l  o  _  w  o  r  l  d  ,  _  م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,   _  h  e  l  l  o  _  w  o  r  l  d \n
598 //      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
599 // VO   H  e  l  l  o  _  w  o  r  l  d  ,  _  م  ل  ا  ع   ل  ا  ب  _  ا   ب  ح  ر  م  ,   _  h  e  l  l  o  _  w  o  r  l  d \n
600 //      0  1  2  3  4  5  6  7  8  9 10 11 12 25 24 23 22 21 20 19 18 17 16 15 14 13 26 27 28 29 30 31 32 33 34 35 36 37 38 39
601
602 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,  _  h  e  l  l  o  _  w  o  r  l  d   ,  _  م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
603 //     40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
604 // VO  \n  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م  _  ,  h  e  l  l  o  _  w  o  r  l  d   _  ,  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
605 //     81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 55 56 57 58 59 60 61 62 63 64 65 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40
606
607 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
608 //     82 83 84 85 86 87 88 89 90 91 92 93 94 95
609 // VO  \n  م  ل  ا  ع  ل   ا  ب  _  ا   ب  ح  ر  م
610 //     95 94 93 92 91 90 89 88 87 86 85 84 83 82
611
612
613 // LO   h   e   l   l   o   _   w   o   r   l   d
614 //     96  97  98  99 100 101 102 103 104 105 106
615 // VO   h   e   l   l   o   _   w   o   r   l   d
616 //     96  97  98  99 100 101 102 103 104 105 106
617
618   unsigned int visualToLogical05[] = { 0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
619   unsigned int  cachedBidiLine05[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u };
620
621 // size 300, 300
622 // LO   H  e  l  l  o  _  w  o  r  l  d  ,  _  م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,   _
623 //      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
624 // VO   H  e  l  l  o  _  w  o  r  l  d  ,  _  م  ل  ا  ع   ل  ا  ب  _  ا   ب  ح  ر  م  ,   _
625 //      0  1  2  3  4  5  6  7  8  9 10 11 12 25 24 23 22 21 20 19 18 17 16 15 14 13 26 27
626
627 // LO    h  e  l  l  o  _  w  o  r  l  d \n
628 //      28 29 30 31 32 33 34 35 36 37 38 39
629 // VO    h  e  l  l  o  _  w  o  r  l  d \n
630 //      28 29 30 31 32 33 34 35 36 37 38 39
631
632 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,  _  h  e  l  l  o  _  w  o  r  l  d   ,  _
633 //     40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
634 // VO  _  ,  h  e  l  l  o  _  w  o  r  l  d   _  ,  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
635 //     67 66 55 56 57 58 59 60 61 62 63 64 65 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40
636
637 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
638 //     68 69 70 71 72 73 74 75 76 77 78 79 80 81
639 // VO  \n  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
640 //     81 80 79 78 77 76 75 74 73 72 71 70 69 68
641
642 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
643 //     82 83 84 85 86 87 88 89 90 91 92 93 94 95
644 // VO  \n  م  ل  ا  ع  ل   ا  ب  _  ا   ب  ح  ر  م
645 //     95 94 93 92 91 90 89 88 87 86 85 84 83 82
646
647
648 // LO   h   e   l   l   o   _   w   o   r   l   d
649 //     96  97  98  99 100 101 102 103 104 105 106
650 // VO   h   e   l   l   o   _   w   o   r   l   d
651 //     96  97  98  99 100 101 102 103 104 105 106
652
653   unsigned int visualToLogical06[] = { 0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
654   unsigned int  cachedBidiLine06[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
655                                        0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
656                                        1u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u,
657                                        2u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u,
658                                        3u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u,
659                                        4u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u,
660                                        5u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u,
661                                        6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u };
662
663 // size 100, 600
664 // LO   H  e  l  l  o  _  w  o  r  l  d  ,  _
665 //      0  1  2  3  4  5  6  7  8  9 10 11 12
666 // VO   H  e  l  l  o  _  w  o  r  l  d  ,  _
667 //      0  1  2  3  4  5  6  7  8  9 10 11 12
668
669 // LO    م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,   _
670 //      13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
671 // VO    م  ل  ا  ع   ل  ا  ب  _  ا   ب  ح  ر  م  ,   _
672 //      25 24 23 22 21 20 19 18 17 16 15 14 13 26 27
673
674 // LO    h  e  l  l  o  _  w  o  r  l  d \n
675 //      28 29 30 31 32 33 34 35 36 37 38 39
676 // VO    h  e  l  l  o  _  w  o  r  l  d \n
677 //      28 29 30 31 32 33 34 35 36 37 38 39
678
679 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,  _
680 //     40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
681 // VO   _  ,  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
682 //     54 53 52 51 50 49 48 47 46 45 44 43 42 41 40
683
684 // LO   h  e  l  l  o  _  w  o  r  l  d   ,  _
685 //     55 56 57 58 59 60 61 62 63 64 65 66 67
686 // VO   _  ,  h  e  l  l  o  _  w  o  r  l  d
687 //     67 66 55 56 57 58 59 60 61 62 63 64 65
688
689 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
690 //     68 69 70 71 72 73 74 75 76 77 78 79 80 81
691 // VO  \n  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
692 //     81 80 79 78 77 76 75 74 73 72 71 70 69 68
693
694 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
695 //     82 83 84 85 86 87 88 89 90 91 92 93 94 95
696 // VO  \n  م  ل  ا  ع  ل   ا  ب  _  ا   ب  ح  ر  م
697 //     95 94 93 92 91 90 89 88 87 86 85 84 83 82
698
699
700 // LO   h   e   l   l   o   _   w   o   r   l   d
701 //     96  97  98  99 100 101 102 103 104 105 106
702 // VO   h   e   l   l   o   _   w   o   r   l   d
703 //     96  97  98  99 100 101 102 103 104 105 106
704
705   struct GetLogicalCharacterIndexData data[] =
706   {
707     {
708       "Zero characters text",
709       "",
710       Size( 300.f, 300.f ),
711       0u,
712       visualToLogical01,
713       cachedBidiLine01
714     },
715     {
716       "Left to right text only",
717       "Hello world",
718       Size( 300.f, 300.f ),
719       11u,
720       visualToLogical02,
721       cachedBidiLine02
722     },
723     {
724       "Right to left text only",
725       "مرحبا بالعالم",
726       Size( 300.f, 300.f ),
727       13u,
728       visualToLogical03,
729       cachedBidiLine03
730     },
731     {
732       "Mix of left to right and right to left text.",
733       "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
734       Size( 300.f, 300.f ),
735       107u,
736       visualToLogical04,
737       cachedBidiLine04
738     },
739     {
740       "Mix of left to right and right to left text.",
741       "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
742       Size( 200.f, 400.f ),
743       107u,
744       visualToLogical05,
745       cachedBidiLine05
746     },
747     {
748       "Mix of left to right and right to left text.",
749       "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
750       Size( 100.f, 600.f ),
751       107u,
752       visualToLogical06,
753       cachedBidiLine06
754     },
755   };
756   const unsigned int numberOfTests = 6u;
757
758   for( unsigned int index = 0u; index < numberOfTests; ++index )
759   {
760     ToolkitTestApplication application;
761     if( !GetLogicalCharacterIndexTest( data[index] ) )
762     {
763       tet_result(TET_FAIL);
764     }
765   }
766
767   tet_result(TET_PASS);
768   END_TEST;
769 }
770
771 int UtcDaliGetLogicalCursorIndex(void)
772 {
773   tet_infoline(" UtcDaliGetLogicalCursorIndex");
774
775   const std::string fontFamily( "TizenSans" );
776   const std::string fontFamilyHebrew( "TizenSansHebrew" );
777
778
779
780   unsigned int visualIndex01[] = { 10u };
781   unsigned int characterIndex01[] = { 0u };
782   unsigned int logicalIndex01[] = { 10u };
783   unsigned int bidirectionalLineIndex01[] = { 0u };
784
785   //  0           11
786   //   Hello world  \n
787   // 12    16
788   //   demo
789
790   // Set a known font description
791   FontDescriptionRun fontDescriptionRun02;
792   fontDescriptionRun02.characterRun.characterIndex = 0u;
793   fontDescriptionRun02.characterRun.numberOfCharacters = 11u;
794   fontDescriptionRun02.familyLength = fontFamily.size();
795   fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
796   memcpy( fontDescriptionRun02.familyName, fontFamily.c_str(), fontDescriptionRun02.familyLength );
797   fontDescriptionRun02.familyDefined = true;
798   fontDescriptionRun02.weightDefined = false;
799   fontDescriptionRun02.widthDefined = false;
800   fontDescriptionRun02.slantDefined = false;
801   fontDescriptionRun02.sizeDefined = false;
802
803   Vector<FontDescriptionRun> fontDescriptionRuns02;
804   fontDescriptionRuns02.PushBack( fontDescriptionRun02 );
805
806   unsigned int visualIndex02[] = { 0u, 16u, 11u, 12u };
807   unsigned int characterIndex02[] = { 0u, 0u, 0u, 0u };
808   unsigned int logicalIndex02[] = { 0u, 16u, 11u, 12u };
809   unsigned int bidirectionalLineIndex02[] = { 0u, 0u, 0u, 0u };
810
811 // LO     H  e  l  l  o  _  w  o  r  l  d  \n
812 //       0  1  2  3  4  5  6  7  8  9 10 11  12
813 // VO     H  e  l  l  o  _  w  o  r  l  d  \n
814
815 // LO         ש  ל  ו  ם  _  ע  ו  ל  ם \n
816 //          12 13 14 15 16 17 18 19 20 21  22
817 // VO     \n  ם  ל  ו  ע _  ם  ו  ל  ש
818
819 // LO      h  e  l  l  o  _  w  o  r  l  d  _  ש  ל  ו  ם  _  ע ו  ל  ם  \n
820 //       22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43  44
821 // VO      h  e  l  l  o  _  w  o  r  l  d  _  ם  ל  ו  ע  _  ם  ו  ל  ש  \n
822
823 // LO      ש  ל  ו  ם  _  ע  ו  ל  ם  _  h  e  l  l  o  _  w  o  r   l  d \n
824 //       44 45 46 47 48 49 50 51  52 52 54 55 56 57 58 59 60 61 62 63  64 65 66
825 // VO      \n h  e  l  l  o  _  w   o  r  l  d  _  ם  ל  ו  ע  _  ם  ו  ל  ש
826
827
828   // Set a known font description
829   FontDescriptionRun fontDescriptionRun0301;
830   fontDescriptionRun0301.characterRun.characterIndex = 0u;
831   fontDescriptionRun0301.characterRun.numberOfCharacters = 12u;
832   fontDescriptionRun0301.familyLength = fontFamily.size();
833   fontDescriptionRun0301.familyName = new char[fontDescriptionRun0301.familyLength];
834   memcpy( fontDescriptionRun0301.familyName, fontFamily.c_str(), fontDescriptionRun0301.familyLength );
835   fontDescriptionRun0301.familyDefined = true;
836   fontDescriptionRun0301.weightDefined = false;
837   fontDescriptionRun0301.widthDefined = false;
838   fontDescriptionRun0301.slantDefined = false;
839   fontDescriptionRun0301.sizeDefined = false;
840
841   // Set a known font description
842   FontDescriptionRun fontDescriptionRun0302;
843   fontDescriptionRun0302.characterRun.characterIndex = 12u;
844   fontDescriptionRun0302.characterRun.numberOfCharacters = 10u;
845   fontDescriptionRun0302.familyLength = fontFamilyHebrew.size();
846   fontDescriptionRun0302.familyName = new char[fontDescriptionRun0302.familyLength];
847   memcpy( fontDescriptionRun0302.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0302.familyLength );
848   fontDescriptionRun0302.familyDefined = true;
849   fontDescriptionRun0302.weightDefined = false;
850   fontDescriptionRun0302.widthDefined = false;
851   fontDescriptionRun0302.slantDefined = false;
852   fontDescriptionRun0302.sizeDefined = false;
853
854   // Set a known font description
855   FontDescriptionRun fontDescriptionRun0303;
856   fontDescriptionRun0303.characterRun.characterIndex = 22u;
857   fontDescriptionRun0303.characterRun.numberOfCharacters = 12u;
858   fontDescriptionRun0303.familyLength = fontFamily.size();
859   fontDescriptionRun0303.familyName = new char[fontDescriptionRun0303.familyLength];
860   memcpy( fontDescriptionRun0303.familyName, fontFamily.c_str(), fontDescriptionRun0303.familyLength );
861   fontDescriptionRun0303.familyDefined = true;
862   fontDescriptionRun0303.weightDefined = false;
863   fontDescriptionRun0303.widthDefined = false;
864   fontDescriptionRun0303.slantDefined = false;
865   fontDescriptionRun0303.sizeDefined = false;
866
867   // Set a known font description
868   FontDescriptionRun fontDescriptionRun0304;
869   fontDescriptionRun0304.characterRun.characterIndex = 34u;
870   fontDescriptionRun0304.characterRun.numberOfCharacters = 20u;
871   fontDescriptionRun0304.familyLength = fontFamilyHebrew.size();
872   fontDescriptionRun0304.familyName = new char[fontDescriptionRun0304.familyLength];
873   memcpy( fontDescriptionRun0304.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0304.familyLength );
874   fontDescriptionRun0304.familyDefined = true;
875   fontDescriptionRun0304.weightDefined = false;
876   fontDescriptionRun0304.widthDefined = false;
877   fontDescriptionRun0304.slantDefined = false;
878   fontDescriptionRun0304.sizeDefined = false;
879
880   // Set a known font description
881   FontDescriptionRun fontDescriptionRun0305;
882   fontDescriptionRun0305.characterRun.characterIndex = 54u;
883   fontDescriptionRun0305.characterRun.numberOfCharacters = 12u;
884   fontDescriptionRun0305.familyLength = fontFamily.size();
885   fontDescriptionRun0305.familyName = new char[fontDescriptionRun0305.familyLength];
886   memcpy( fontDescriptionRun0305.familyName, fontFamily.c_str(), fontDescriptionRun0305.familyLength );
887   fontDescriptionRun0305.familyDefined = true;
888   fontDescriptionRun0305.weightDefined = false;
889   fontDescriptionRun0305.widthDefined = false;
890   fontDescriptionRun0305.slantDefined = false;
891   fontDescriptionRun0305.sizeDefined = false;
892
893   Vector<FontDescriptionRun> fontDescriptionRuns03;
894   fontDescriptionRuns03.PushBack( fontDescriptionRun0301 );
895   fontDescriptionRuns03.PushBack( fontDescriptionRun0302 );
896   fontDescriptionRuns03.PushBack( fontDescriptionRun0303 );
897   fontDescriptionRuns03.PushBack( fontDescriptionRun0304 );
898   fontDescriptionRuns03.PushBack( fontDescriptionRun0305 );
899
900   unsigned int visualIndex03[] = {  0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u,
901                                    13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u, 21u, 22u,
902                                    22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 40u, 41u, 42u, 43u,
903                                    45u, 46u, 47u, 48u, 49u, 50u, 51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 66u };
904
905   unsigned int characterIndex03[] = {  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,
906                                       12u, 12u, 12u, 12u, 12u, 12u, 12u, 12u, 12u, 12u,
907                                       22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u,
908                                       44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u};
909
910   unsigned int logicalIndex03[] = {  0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u,
911                                     21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 12u,
912                                     22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 42u, 41u, 40u, 39u, 38u, 37u, 36u, 35u, 43u,
913                                     65u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u };
914
915   unsigned int bidirectionalLineIndex03[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
916                                               0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
917                                               1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
918                                               2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u };
919
920
921 // LO     ש  ל  ו  ם  _  ע  ו  ל  ם \n
922 //       0  1  2  3  4  5  6  7  8  9 10
923 // VO  \n ם  ל  ו  ע  _  ם  ו  ל  ש
924
925 //      h  e  l  l  o  _  w  o  r  l  d  \n
926 // LO 10 11 12 13 14 15 16 17 18 19 20 21 22
927 //      h  e  l  l  o  _  w  o  r  l  d  \n
928
929 //         ש  ל  ו  ם  _  ע  ו  ל  ם _  h  e  l  l  o  _  w  o  r  l  d  \n
930 // LO    22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
931 //     \n  h  e  l  l  o  _  w  o  r  l  d  _  ם  ל  ו  ע  _  ם  ו  ל  ש
932
933 //      h  e  l  l  o  _  w  o  r  l  d  _  ש  ל  ו  ם  _  ע  ו  ל  ם \n
934 // LO 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
935 //      h  e  l  l  o  _  w  o  r  l  d  _  ם  ל  ו  ע  _  ם  ו  ל  ש \n
936
937   // Set a known font description
938   FontDescriptionRun fontDescriptionRun0401;
939   fontDescriptionRun0401.characterRun.characterIndex = 0u;
940   fontDescriptionRun0401.characterRun.numberOfCharacters = 10u;
941   fontDescriptionRun0401.familyLength = fontFamilyHebrew.size();
942   fontDescriptionRun0401.familyName = new char[fontDescriptionRun0401.familyLength];
943   memcpy( fontDescriptionRun0401.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0401.familyLength );
944   fontDescriptionRun0401.familyDefined = true;
945   fontDescriptionRun0401.weightDefined = false;
946   fontDescriptionRun0401.widthDefined = false;
947   fontDescriptionRun0401.slantDefined = false;
948   fontDescriptionRun0401.sizeDefined = false;
949
950   FontDescriptionRun fontDescriptionRun0402;
951   fontDescriptionRun0402.characterRun.characterIndex = 10u;
952   fontDescriptionRun0402.characterRun.numberOfCharacters = 12u;
953   fontDescriptionRun0402.familyLength = fontFamily.size();
954   fontDescriptionRun0402.familyName = new char[fontDescriptionRun0402.familyLength];
955   memcpy( fontDescriptionRun0402.familyName, fontFamily.c_str(), fontDescriptionRun0402.familyLength );
956   fontDescriptionRun0402.familyDefined = true;
957   fontDescriptionRun0402.weightDefined = false;
958   fontDescriptionRun0402.widthDefined = false;
959   fontDescriptionRun0402.slantDefined = false;
960   fontDescriptionRun0402.sizeDefined = false;
961
962   FontDescriptionRun fontDescriptionRun0403;
963   fontDescriptionRun0403.characterRun.characterIndex = 22u;
964   fontDescriptionRun0403.characterRun.numberOfCharacters = 10u;
965   fontDescriptionRun0403.familyLength = fontFamilyHebrew.size();
966   fontDescriptionRun0403.familyName = new char[fontDescriptionRun0403.familyLength];
967   memcpy( fontDescriptionRun0403.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0403.familyLength );
968   fontDescriptionRun0403.familyDefined = true;
969   fontDescriptionRun0403.weightDefined = false;
970   fontDescriptionRun0403.widthDefined = false;
971   fontDescriptionRun0403.slantDefined = false;
972   fontDescriptionRun0403.sizeDefined = false;
973
974   FontDescriptionRun fontDescriptionRun0404;
975   fontDescriptionRun0404.characterRun.characterIndex = 32u;
976   fontDescriptionRun0404.characterRun.numberOfCharacters = 24u;
977   fontDescriptionRun0404.familyLength = fontFamily.size();
978   fontDescriptionRun0404.familyName = new char[fontDescriptionRun0404.familyLength];
979   memcpy( fontDescriptionRun0404.familyName, fontFamily.c_str(), fontDescriptionRun0404.familyLength );
980   fontDescriptionRun0404.familyDefined = true;
981   fontDescriptionRun0404.weightDefined = false;
982   fontDescriptionRun0404.widthDefined = false;
983   fontDescriptionRun0404.slantDefined = false;
984   fontDescriptionRun0404.sizeDefined = false;
985
986   FontDescriptionRun fontDescriptionRun0405;
987   fontDescriptionRun0405.characterRun.characterIndex = 56u;
988   fontDescriptionRun0405.characterRun.numberOfCharacters = 10u;
989   fontDescriptionRun0405.familyLength = fontFamilyHebrew.size();
990   fontDescriptionRun0405.familyName = new char[fontDescriptionRun0405.familyLength];
991   memcpy( fontDescriptionRun0405.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0405.familyLength );
992   fontDescriptionRun0405.familyDefined = true;
993   fontDescriptionRun0405.weightDefined = false;
994   fontDescriptionRun0405.widthDefined = false;
995   fontDescriptionRun0405.slantDefined = false;
996   fontDescriptionRun0405.sizeDefined = false;
997
998   Vector<FontDescriptionRun> fontDescriptionRuns04;
999   fontDescriptionRuns04.PushBack( fontDescriptionRun0401 );
1000   fontDescriptionRuns04.PushBack( fontDescriptionRun0402 );
1001   fontDescriptionRuns04.PushBack( fontDescriptionRun0403 );
1002   fontDescriptionRuns04.PushBack( fontDescriptionRun0404 );
1003   fontDescriptionRuns04.PushBack( fontDescriptionRun0405 );
1004
1005   unsigned int  visualIndex04[] = {  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u,
1006                                     10u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u, 21u,
1007                                     23u, 24u, 25u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 40u, 41u, 42u, 43u, 44u,
1008                                     44u, 45u, 46u, 47u, 48u, 49u, 50u, 51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u };
1009
1010   unsigned int characterIndex04[] = {  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,
1011                                       10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u,
1012                                       22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u,
1013                                       44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u };
1014
1015   unsigned int logicalIndex04[] = {  9u,  8u,  7u,  6u,  5u,  4u,  3u,  2u,  1u,  0u,
1016                                     10u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u, 21u,
1017                                     43u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 40u, 41u, 42u, 32u, 31u, 30u, 29u, 28u, 27u, 26u, 25u, 24u, 23u, 22u,
1018                                     44u, 45u, 46u, 47u, 48u, 49u, 50u, 51u, 52u, 53u, 54u, 55u, 56u, 64u, 63u, 62u, 61u, 60u, 59u, 58u, 57u, 65u };
1019
1020   unsigned int bidirectionalLineIndex04[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
1021                                               0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
1022                                               1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
1023                                               2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u };
1024
1025 // LO   A  B  C  D  E  F  G  H  I  J  K
1026 //     0  1  2  3  4  5  6  7  8  9 10 11
1027 // LO   L  M  N
1028 //    11 12 13 14
1029
1030   // Set a known font description
1031   FontDescriptionRun fontDescriptionRun0501;
1032   fontDescriptionRun0501.characterRun.characterIndex = 0u;
1033   fontDescriptionRun0501.characterRun.numberOfCharacters = 14u;
1034   fontDescriptionRun0501.familyLength = fontFamily.size();
1035   fontDescriptionRun0501.familyName = new char[fontDescriptionRun0501.familyLength];
1036   memcpy( fontDescriptionRun0501.familyName, fontFamily.c_str(), fontDescriptionRun0501.familyLength );
1037   fontDescriptionRun0501.familyDefined = true;
1038   fontDescriptionRun0501.weightDefined = false;
1039   fontDescriptionRun0501.widthDefined = false;
1040   fontDescriptionRun0501.slantDefined = false;
1041   fontDescriptionRun0501.sizeDefined = false;
1042
1043   Vector<FontDescriptionRun> fontDescriptionRuns05;
1044   fontDescriptionRuns05.PushBack( fontDescriptionRun0501 );
1045
1046   unsigned int  visualIndex05[] = {  0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u,
1047                                     11u, 12u, 13u, 14u };
1048
1049   unsigned int characterIndex05[] = { 0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,
1050                                       11u, 11u, 11u, 11u };
1051
1052   unsigned int logicalIndex05[] = { 0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u,
1053                                     11u, 12u, 13u, 14u };
1054
1055   unsigned int bidirectionalLineIndex05[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
1056                                               0u, 0u, 0u, 0u };
1057
1058 // LO      ק  ר  א  ט  ו  ן  ם  פ  ש  ד  ג  כ
1059 //        0  1  2  3  4  5  6  7  8  9  10 11 12
1060 // VO      כ  ג  ד  ש  פ  ם  ן  ו  ט  א  ר  ק
1061
1062 // LO      ע  י  ח  ל
1063 //       12 13 14 15 16
1064 // VO      ל  ח  י  ע
1065
1066
1067   // Set a known font description
1068   FontDescriptionRun fontDescriptionRun0601;
1069   fontDescriptionRun0601.characterRun.characterIndex = 0u;
1070   fontDescriptionRun0601.characterRun.numberOfCharacters = 16u;
1071   fontDescriptionRun0601.familyLength = fontFamilyHebrew.size();
1072   fontDescriptionRun0601.familyName = new char[fontDescriptionRun0601.familyLength];
1073   memcpy( fontDescriptionRun0601.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0601.familyLength );
1074   fontDescriptionRun0601.familyDefined = true;
1075   fontDescriptionRun0601.weightDefined = false;
1076   fontDescriptionRun0601.widthDefined = false;
1077   fontDescriptionRun0601.slantDefined = false;
1078   fontDescriptionRun0601.sizeDefined = false;
1079
1080   Vector<FontDescriptionRun> fontDescriptionRuns06;
1081   fontDescriptionRuns06.PushBack( fontDescriptionRun0601 );
1082
1083   unsigned int  visualIndex06[] = {  0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u, 12u,
1084                                     12u, 13u, 14u, 15u, 16u };
1085
1086   unsigned int characterIndex06[] = {  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,
1087                                       12u, 12u, 12u, 12u, 12u };
1088
1089   unsigned int logicalIndex06[] = { 12u, 11u, 10u,  9u,  8u,  7u,  6u,  5u,  4u,  3u,  2u,  1u, 0u,
1090                                     16u, 15u, 14u, 13u, 12u };
1091
1092   unsigned int bidirectionalLineIndex06[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
1093                                               1u, 1u, 1u, 1u, 1u, };
1094
1095   struct GetLogicalCursorIndexData data[] =
1096   {
1097     {
1098       "Zero characters text",
1099       "",
1100       Size( 300.f, 300.f ),
1101       0u,
1102       nullptr,
1103       1u,
1104       visualIndex01,
1105       characterIndex01,
1106       logicalIndex01,
1107       bidirectionalLineIndex01,
1108     },
1109     {
1110       "All left to right text 01.",
1111       "Hello world\ndemo",
1112       Size( 300.f, 300.f ),
1113       1u,
1114       fontDescriptionRuns02.Begin(),
1115       4u,
1116       visualIndex02,
1117       characterIndex02,
1118       logicalIndex02,
1119       bidirectionalLineIndex02,
1120     },
1121     {
1122       "bidirectional text 01.",
1123       "Hello world\nשלום עולם\nhello world שלום עולם\nשלום עולם hello world\n",
1124       Size( 300.f, 300.f ),
1125       5u,
1126       fontDescriptionRuns03.Begin(),
1127       65u,
1128       visualIndex03,
1129       characterIndex03,
1130       logicalIndex03,
1131       bidirectionalLineIndex03,
1132     },
1133     {
1134       "bidirectional text 02.",
1135       "שלום עולם\nhello world\nשלום עולם hello world\nhello world שלום עולם\n",
1136       Size( 300.f, 300.f ),
1137       5u,
1138       fontDescriptionRuns04.Begin(),
1139       65u,
1140       visualIndex04,
1141       characterIndex04,
1142       logicalIndex04,
1143       bidirectionalLineIndex04,
1144     },
1145     {
1146       "long line 01.",
1147       "ABCDEFGHIJKLMN",
1148       Size( 100.f, 300.f ),
1149       1u,
1150       fontDescriptionRuns05.Begin(),
1151       13u,
1152       visualIndex05,
1153       characterIndex05,
1154       logicalIndex05,
1155       bidirectionalLineIndex05,
1156     },
1157     {
1158       "bidirectional text 03.",
1159       "קראטוןםפשדגכעיחל",
1160       Size( 100.f, 300.f ),
1161       1u,
1162       fontDescriptionRuns06.Begin(),
1163       18u,
1164       visualIndex06,
1165       characterIndex06,
1166       logicalIndex06,
1167       bidirectionalLineIndex06,
1168     },
1169   };
1170   const unsigned int numberOfTests = 6u;
1171
1172   for( unsigned int index = 0u; index < numberOfTests; ++index )
1173   {
1174     ToolkitTestApplication application;
1175     if( !GetLogicalCursorIndexTest( data[index] ) )
1176     {
1177       tet_printf("Test %d failed : [%s]\n", index, data[index].description.c_str());
1178       tet_result(TET_FAIL);
1179     }
1180   }
1181
1182   tet_result(TET_PASS);
1183   END_TEST;
1184 }