Fix the incorrect offset of text outline
[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
347     if( logicalModel->mBidirectionalLineIndex != data.cachedBidiLine[index] )
348     {
349       tet_printf( "  test : %d, different cached line index : %d, expected : %d\n", index, logicalModel->mBidirectionalLineIndex, data.cachedBidiLine[index] );
350       return false;
351     }
352
353     const CharacterIndex visualCharacterIndex = data.visualCursorIndex[index];
354     const CharacterIndex logicalCursorIndex = fetched ? logicalModel->GetLogicalCursorIndex( visualCharacterIndex ) : visualCharacterIndex;
355
356     if( logicalCursorIndex != data.logicalCursorIndex[index] )
357     {
358       tet_printf( "  test : %d, visual index : %d, different logical cursor index :%d, expected : %d", index, visualCharacterIndex, logicalCursorIndex, data.logicalCursorIndex[index] );
359       return false;
360     }
361   }
362
363   return true;
364 }
365
366 } // namespace
367
368 //////////////////////////////////////////////////////////
369 //
370 // UtcDaliCreateParagraph
371 // UtcDaliFindParagraph
372 // UtcDaliFetchBidirectionalLineInfo
373 // UtcDaliGetLogicalCharacterIndex
374 // UtcDaliGetLogicalCursorIndex
375 //
376 //////////////////////////////////////////////////////////
377
378 int UtcDaliCreateParagraph(void)
379 {
380   tet_infoline(" UtcDaliCreateParagraph");
381
382   unsigned int paragraphsIndices01[] = { 0u };
383   unsigned int paragraphsNumberOfCharacters01[] = { 0u };
384   unsigned int paragraphsIndices02[] = { 0u, 12u, 17u };
385   unsigned int paragraphsNumberOfCharacters02[] = { 12u, 5u, 1u };
386   unsigned int paragraphsIndices03[] = { 0u, 12u, 17u, 34u };
387   unsigned int paragraphsNumberOfCharacters03[] = { 12u, 5u, 17u ,1u };
388
389   struct CreateParagraphData data[] =
390   {
391     {
392       "Zero characters",
393       "",
394       0u,
395       0u,
396       0u,
397       paragraphsIndices01,
398       paragraphsNumberOfCharacters01,
399     },
400     {
401       "Some paragraphs",
402       "Hello world\ndemo\n\n",
403       0u,
404       18u,
405       3u,
406       paragraphsIndices02,
407       paragraphsNumberOfCharacters02,
408     },
409     {
410       "Some paragraphs. Update the initial paragraphs.",
411       "Hello world\ndemo\nhello world demo\n\n",
412       0u,
413       17u,
414       4u,
415       paragraphsIndices03,
416       paragraphsNumberOfCharacters03,
417     },
418     {
419       "Some paragraphs. Update the mid paragraphs.",
420       "Hello world\ndemo\nhello world demo\n\n",
421       12u,
422       5u,
423       4u,
424       paragraphsIndices03,
425       paragraphsNumberOfCharacters03,
426     },
427     {
428       "Some paragraphs. Update the final paragraphs.",
429       "Hello world\ndemo\nhello world demo\n\n",
430       17u,
431       18u,
432       4u,
433       paragraphsIndices03,
434       paragraphsNumberOfCharacters03,
435     },
436   };
437   const unsigned int numberOfTests = 5u;
438
439   for( unsigned int index = 0u; index < numberOfTests; ++index )
440   {
441     ToolkitTestApplication application;
442     if( !CreateParagraphTest( data[index] ) )
443     {
444       tet_result(TET_FAIL);
445     }
446   }
447
448   tet_result(TET_PASS);
449   END_TEST;
450 }
451
452 int UtcDaliFindParagraph(void)
453 {
454   tet_infoline(" UtcDaliFindParagraph");
455
456   unsigned int paragraphs01[] = {};
457   unsigned int paragraphs02[] = { 0u, 1u, 2u };
458   unsigned int paragraphs03[] = { 0u };
459   unsigned int paragraphs04[] = { 1u };
460   unsigned int paragraphs05[] = { 0u, 1u, 2u };
461
462   struct FindParagraphData data[] =
463   {
464     {
465       "Zero characters",
466       "",
467       0u,
468       100u,
469       0u,
470       paragraphs01,
471     },
472     {
473       "Some paragraphs",
474       "Hello world\ndemo\n\n",
475       0u,
476       18u,
477       3u,
478       paragraphs02
479     },
480     {
481       "Some paragraphs",
482       "Hello world\ndemo\n\n",
483       0u,
484       12u,
485       1u,
486       paragraphs03
487     },
488     {
489       "Some paragraphs",
490       "Hello world\ndemo\n\n",
491       12u,
492       5u,
493       1u,
494       paragraphs04
495     },
496     {
497       "Some paragraphs",
498       "Hello world\ndemo\n\n",
499       3u,
500       15u,
501       3u,
502       paragraphs05
503     },
504   };
505   const unsigned int numberOfTests = 5u;
506
507   for( unsigned int index = 0u; index < numberOfTests; ++index )
508   {
509     ToolkitTestApplication application;
510     if( !FindParagraphTest( data[index] ) )
511     {
512       tet_result(TET_FAIL);
513     }
514   }
515
516   tet_result(TET_PASS);
517   END_TEST;
518 }
519
520 int UtcDaliFetchBidirectionalLineInfo(void)
521 {
522   tet_infoline(" UtcDaliFetchBidirectionalLineInfo");
523
524   unsigned int logicalIndex01[] = { 0u };
525   bool fetched01[] = { false };
526   unsigned int bidiLine01[] = { 0u };
527
528   unsigned int logicalIndex02[] = { 3u };
529   bool fetched02[] = { false };
530   unsigned int bidiLine02[] = { 0u };
531
532   unsigned int logicalIndex03[] = { 0u, 11u, 12u, 21u, 22u, 33u, 34u, 43u, 44u, 54u};
533   bool fetched03[] = { false, false, true, true, false, false, true, true, false, false };
534   unsigned int bidiLine03[] = { 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 0u, 0u };
535
536   struct FetchBidirectionalLineInfoData data[] =
537   {
538     {
539       "Void text",
540       "",
541       1u,
542       logicalIndex01,
543       fetched01,
544       bidiLine01
545     },
546     {
547       "LTR text",
548       "Hello world",
549       1u,
550       logicalIndex02,
551       fetched02,
552       bidiLine02
553     },
554     {
555       "Bidi text",
556       "Hello world\nשלום עולם\nhello world\nשלום עולם\nhello world",
557       10u,
558       logicalIndex03,
559       fetched03,
560       bidiLine03
561     }
562   };
563   const unsigned int numberOfTests = 3u;
564
565   for( unsigned int index = 0u; index < numberOfTests; ++index )
566   {
567     ToolkitTestApplication application;
568     if( !FetchBidirectionalLineInfoTest( data[index] ) )
569     {
570       tet_result(TET_FAIL);
571     }
572   }
573
574   tet_result(TET_PASS);
575   END_TEST;
576 }
577
578 int UtcDaliGetLogicalCharacterIndex(void)
579 {
580   tet_infoline(" UtcDaliSetVisualToLogicalMap");
581
582   unsigned int visualToLogical01[] = {};
583   unsigned int  cachedBidiLine01[] = {};
584   unsigned int visualToLogical02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
585   unsigned int  cachedBidiLine02[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,  0u };
586   unsigned int visualToLogical03[] = { 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
587   unsigned int  cachedBidiLine03[] = {  0u,  0u,  0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u };
588
589   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 };
590   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,
591                                        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,
592                                        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 };
593
594 // size 300, 300
595 // LO   H  e  l  l  o  _  w  o  r  l  d  ,  _  م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,   _  h  e  l  l  o  _  w  o  r  l  d \n
596 //      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
597 // VO   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 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
599
600 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,  _  h  e  l  l  o  _  w  o  r  l  d   ,  _  م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
601 //     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
602 // VO  \n  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م  _  ,  h  e  l  l  o  _  w  o  r  l  d   _  ,  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
603 //     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
604
605 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
606 //     82 83 84 85 86 87 88 89 90 91 92 93 94 95
607 // VO  \n  م  ل  ا  ع  ل   ا  ب  _  ا   ب  ح  ر  م
608 //     95 94 93 92 91 90 89 88 87 86 85 84 83 82
609
610
611 // LO   h   e   l   l   o   _   w   o   r   l   d
612 //     96  97  98  99 100 101 102 103 104 105 106
613 // VO   h   e   l   l   o   _   w   o   r   l   d
614 //     96  97  98  99 100 101 102 103 104 105 106
615
616   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 };
617   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 };
618
619 // size 300, 300
620 // LO   H  e  l  l  o  _  w  o  r  l  d  ,  _  م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,   _
621 //      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
622 // VO   H  e  l  l  o  _  w  o  r  l  d  ,  _  م  ل  ا  ع   ل  ا  ب  _  ا   ب  ح  ر  م  ,   _
623 //      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
624
625 // LO    h  e  l  l  o  _  w  o  r  l  d \n
626 //      28 29 30 31 32 33 34 35 36 37 38 39
627 // VO    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
630 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,  _  h  e  l  l  o  _  w  o  r  l  d   ,  _
631 //     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
632 // VO  _  ,  h  e  l  l  o  _  w  o  r  l  d   _  ,  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
633 //     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
634
635 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
636 //     68 69 70 71 72 73 74 75 76 77 78 79 80 81
637 // VO  \n  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
638 //     81 80 79 78 77 76 75 74 73 72 71 70 69 68
639
640 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
641 //     82 83 84 85 86 87 88 89 90 91 92 93 94 95
642 // VO  \n  م  ل  ا  ع  ل   ا  ب  _  ا   ب  ح  ر  م
643 //     95 94 93 92 91 90 89 88 87 86 85 84 83 82
644
645
646 // LO   h   e   l   l   o   _   w   o   r   l   d
647 //     96  97  98  99 100 101 102 103 104 105 106
648 // VO   h   e   l   l   o   _   w   o   r   l   d
649 //     96  97  98  99 100 101 102 103 104 105 106
650
651   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 };
652   unsigned int  cachedBidiLine06[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
653                                        0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
654                                        1u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u,
655                                        2u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u,
656                                        3u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u,
657                                        4u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u,
658                                        5u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u,
659                                        6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u };
660
661 // size 100, 600
662 // LO   H  e  l  l  o  _  w  o  r  l  d  ,  _
663 //      0  1  2  3  4  5  6  7  8  9 10 11 12
664 // VO   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
667 // LO    م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,   _
668 //      13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
669 // VO    م  ل  ا  ع   ل  ا  ب  _  ا   ب  ح  ر  م  ,   _
670 //      25 24 23 22 21 20 19 18 17 16 15 14 13 26 27
671
672 // LO    h  e  l  l  o  _  w  o  r  l  d \n
673 //      28 29 30 31 32 33 34 35 36 37 38 39
674 // VO    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
677 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,  _
678 //     40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
679 // VO   _  ,  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
680 //     54 53 52 51 50 49 48 47 46 45 44 43 42 41 40
681
682 // LO   h  e  l  l  o  _  w  o  r  l  d   ,  _
683 //     55 56 57 58 59 60 61 62 63 64 65 66 67
684 // VO   _  ,  h  e  l  l  o  _  w  o  r  l  d
685 //     67 66 55 56 57 58 59 60 61 62 63 64 65
686
687 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
688 //     68 69 70 71 72 73 74 75 76 77 78 79 80 81
689 // VO  \n  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
690 //     81 80 79 78 77 76 75 74 73 72 71 70 69 68
691
692 // LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
693 //     82 83 84 85 86 87 88 89 90 91 92 93 94 95
694 // VO  \n  م  ل  ا  ع  ل   ا  ب  _  ا   ب  ح  ر  م
695 //     95 94 93 92 91 90 89 88 87 86 85 84 83 82
696
697
698 // LO   h   e   l   l   o   _   w   o   r   l   d
699 //     96  97  98  99 100 101 102 103 104 105 106
700 // VO   h   e   l   l   o   _   w   o   r   l   d
701 //     96  97  98  99 100 101 102 103 104 105 106
702
703   struct GetLogicalCharacterIndexData data[] =
704   {
705     {
706       "Zero characters text",
707       "",
708       Size( 300.f, 300.f ),
709       0u,
710       visualToLogical01,
711       cachedBidiLine01
712     },
713     {
714       "Left to right text only",
715       "Hello world",
716       Size( 300.f, 300.f ),
717       11u,
718       visualToLogical02,
719       cachedBidiLine02
720     },
721     {
722       "Right to left text only",
723       "مرحبا بالعالم",
724       Size( 300.f, 300.f ),
725       13u,
726       visualToLogical03,
727       cachedBidiLine03
728     },
729     {
730       "Mix of left to right and right to left text.",
731       "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
732       Size( 300.f, 300.f ),
733       107u,
734       visualToLogical04,
735       cachedBidiLine04
736     },
737     {
738       "Mix of left to right and right to left text.",
739       "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
740       Size( 200.f, 400.f ),
741       107u,
742       visualToLogical05,
743       cachedBidiLine05
744     },
745     {
746       "Mix of left to right and right to left text.",
747       "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
748       Size( 100.f, 600.f ),
749       107u,
750       visualToLogical06,
751       cachedBidiLine06
752     },
753   };
754   const unsigned int numberOfTests = 6u;
755
756   for( unsigned int index = 0u; index < numberOfTests; ++index )
757   {
758     ToolkitTestApplication application;
759     if( !GetLogicalCharacterIndexTest( data[index] ) )
760     {
761       tet_result(TET_FAIL);
762     }
763   }
764
765   tet_result(TET_PASS);
766   END_TEST;
767 }
768
769 int UtcDaliGetLogicalCursorIndex(void)
770 {
771   tet_infoline(" UtcDaliGetLogicalCursorIndex");
772
773   const std::string fontFamily( "TizenSans" );
774   const std::string fontFamilyHebrew( "TizenSansHebrew" );
775
776
777
778   unsigned int visualIndex01[] = { 10u };
779   unsigned int characterIndex01[] = { 0u };
780   unsigned int logicalIndex01[] = { 10u };
781   unsigned int bidirectionalLineIndex01[] = { 0u };
782
783   //  0           11
784   //   Hello world  \n
785   // 12    16
786   //   demo
787
788   // Set a known font description
789   FontDescriptionRun fontDescriptionRun02;
790   fontDescriptionRun02.characterRun.characterIndex = 0u;
791   fontDescriptionRun02.characterRun.numberOfCharacters = 11u;
792   fontDescriptionRun02.familyLength = fontFamily.size();
793   fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
794   memcpy( fontDescriptionRun02.familyName, fontFamily.c_str(), fontDescriptionRun02.familyLength );
795   fontDescriptionRun02.familyDefined = true;
796   fontDescriptionRun02.weightDefined = false;
797   fontDescriptionRun02.widthDefined = false;
798   fontDescriptionRun02.slantDefined = false;
799   fontDescriptionRun02.sizeDefined = false;
800
801   Vector<FontDescriptionRun> fontDescriptionRuns02;
802   fontDescriptionRuns02.PushBack( fontDescriptionRun02 );
803
804   unsigned int visualIndex02[] = { 0u, 16u, 11u, 12u };
805   unsigned int characterIndex02[] = { 0u, 0u, 0u, 0u };
806   unsigned int logicalIndex02[] = { 0u, 16u, 11u, 12u };
807   unsigned int bidirectionalLineIndex02[] = { 0u, 0u, 0u, 0u };
808
809 // LO     H  e  l  l  o  _  w  o  r  l  d  \n
810 //       0  1  2  3  4  5  6  7  8  9 10 11  12
811 // VO     H  e  l  l  o  _  w  o  r  l  d  \n
812
813 // LO         ש  ל  ו  ם  _  ע  ו  ל  ם \n
814 //          12 13 14 15 16 17 18 19 20 21  22
815 // VO     \n  ם  ל  ו  ע _  ם  ו  ל  ש
816
817 // LO      h  e  l  l  o  _  w  o  r  l  d  _  ש  ל  ו  ם  _  ע ו  ל  ם  \n
818 //       22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43  44
819 // VO      h  e  l  l  o  _  w  o  r  l  d  _  ם  ל  ו  ע  _  ם  ו  ל  ש  \n
820
821 // LO      ש  ל  ו  ם  _  ע  ו  ל  ם  _  h  e  l  l  o  _  w  o  r   l  d \n
822 //       44 45 46 47 48 49 50 51  52 52 54 55 56 57 58 59 60 61 62 63  64 65 66
823 // VO      \n h  e  l  l  o  _  w   o  r  l  d  _  ם  ל  ו  ע  _  ם  ו  ל  ש
824
825
826   // Set a known font description
827   FontDescriptionRun fontDescriptionRun0301;
828   fontDescriptionRun0301.characterRun.characterIndex = 0u;
829   fontDescriptionRun0301.characterRun.numberOfCharacters = 12u;
830   fontDescriptionRun0301.familyLength = fontFamily.size();
831   fontDescriptionRun0301.familyName = new char[fontDescriptionRun0301.familyLength];
832   memcpy( fontDescriptionRun0301.familyName, fontFamily.c_str(), fontDescriptionRun0301.familyLength );
833   fontDescriptionRun0301.familyDefined = true;
834   fontDescriptionRun0301.weightDefined = false;
835   fontDescriptionRun0301.widthDefined = false;
836   fontDescriptionRun0301.slantDefined = false;
837   fontDescriptionRun0301.sizeDefined = false;
838
839   // Set a known font description
840   FontDescriptionRun fontDescriptionRun0302;
841   fontDescriptionRun0302.characterRun.characterIndex = 12u;
842   fontDescriptionRun0302.characterRun.numberOfCharacters = 10u;
843   fontDescriptionRun0302.familyLength = fontFamilyHebrew.size();
844   fontDescriptionRun0302.familyName = new char[fontDescriptionRun0302.familyLength];
845   memcpy( fontDescriptionRun0302.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0302.familyLength );
846   fontDescriptionRun0302.familyDefined = true;
847   fontDescriptionRun0302.weightDefined = false;
848   fontDescriptionRun0302.widthDefined = false;
849   fontDescriptionRun0302.slantDefined = false;
850   fontDescriptionRun0302.sizeDefined = false;
851
852   // Set a known font description
853   FontDescriptionRun fontDescriptionRun0303;
854   fontDescriptionRun0303.characterRun.characterIndex = 22u;
855   fontDescriptionRun0303.characterRun.numberOfCharacters = 12u;
856   fontDescriptionRun0303.familyLength = fontFamily.size();
857   fontDescriptionRun0303.familyName = new char[fontDescriptionRun0303.familyLength];
858   memcpy( fontDescriptionRun0303.familyName, fontFamily.c_str(), fontDescriptionRun0303.familyLength );
859   fontDescriptionRun0303.familyDefined = true;
860   fontDescriptionRun0303.weightDefined = false;
861   fontDescriptionRun0303.widthDefined = false;
862   fontDescriptionRun0303.slantDefined = false;
863   fontDescriptionRun0303.sizeDefined = false;
864
865   // Set a known font description
866   FontDescriptionRun fontDescriptionRun0304;
867   fontDescriptionRun0304.characterRun.characterIndex = 34u;
868   fontDescriptionRun0304.characterRun.numberOfCharacters = 20u;
869   fontDescriptionRun0304.familyLength = fontFamilyHebrew.size();
870   fontDescriptionRun0304.familyName = new char[fontDescriptionRun0304.familyLength];
871   memcpy( fontDescriptionRun0304.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0304.familyLength );
872   fontDescriptionRun0304.familyDefined = true;
873   fontDescriptionRun0304.weightDefined = false;
874   fontDescriptionRun0304.widthDefined = false;
875   fontDescriptionRun0304.slantDefined = false;
876   fontDescriptionRun0304.sizeDefined = false;
877
878   // Set a known font description
879   FontDescriptionRun fontDescriptionRun0305;
880   fontDescriptionRun0305.characterRun.characterIndex = 54u;
881   fontDescriptionRun0305.characterRun.numberOfCharacters = 12u;
882   fontDescriptionRun0305.familyLength = fontFamily.size();
883   fontDescriptionRun0305.familyName = new char[fontDescriptionRun0305.familyLength];
884   memcpy( fontDescriptionRun0305.familyName, fontFamily.c_str(), fontDescriptionRun0305.familyLength );
885   fontDescriptionRun0305.familyDefined = true;
886   fontDescriptionRun0305.weightDefined = false;
887   fontDescriptionRun0305.widthDefined = false;
888   fontDescriptionRun0305.slantDefined = false;
889   fontDescriptionRun0305.sizeDefined = false;
890
891   Vector<FontDescriptionRun> fontDescriptionRuns03;
892   fontDescriptionRuns03.PushBack( fontDescriptionRun0301 );
893   fontDescriptionRuns03.PushBack( fontDescriptionRun0302 );
894   fontDescriptionRuns03.PushBack( fontDescriptionRun0303 );
895   fontDescriptionRuns03.PushBack( fontDescriptionRun0304 );
896   fontDescriptionRuns03.PushBack( fontDescriptionRun0305 );
897
898   unsigned int visualIndex03[] = {  0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u,
899                                    13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u, 21u, 22u,
900                                    22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 40u, 41u, 42u, 43u,
901                                    45u, 46u, 47u, 48u, 49u, 50u, 51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 66u };
902
903   unsigned int characterIndex03[] = {  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,
904                                       12u, 12u, 12u, 12u, 12u, 12u, 12u, 12u, 12u, 12u,
905                                       22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u,
906                                       44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u};
907
908   unsigned int logicalIndex03[] = {  0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u,
909                                     21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 12u,
910                                     22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 42u, 41u, 40u, 39u, 38u, 37u, 36u, 35u, 43u,
911                                     65u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u };
912
913   unsigned int bidirectionalLineIndex03[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
914                                               0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
915                                               1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
916                                               2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u };
917
918
919 // LO     ש  ל  ו  ם  _  ע  ו  ל  ם \n
920 //       0  1  2  3  4  5  6  7  8  9 10
921 // VO  \n ם  ל  ו  ע  _  ם  ו  ל  ש
922
923 //      h  e  l  l  o  _  w  o  r  l  d  \n
924 // LO 10 11 12 13 14 15 16 17 18 19 20 21 22
925 //      h  e  l  l  o  _  w  o  r  l  d  \n
926
927 //         ש  ל  ו  ם  _  ע  ו  ל  ם _  h  e  l  l  o  _  w  o  r  l  d  \n
928 // LO    22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
929 //     \n  h  e  l  l  o  _  w  o  r  l  d  _  ם  ל  ו  ע  _  ם  ו  ל  ש
930
931 //      h  e  l  l  o  _  w  o  r  l  d  _  ש  ל  ו  ם  _  ע  ו  ל  ם \n
932 // LO 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
933 //      h  e  l  l  o  _  w  o  r  l  d  _  ם  ל  ו  ע  _  ם  ו  ל  ש \n
934
935   // Set a known font description
936   FontDescriptionRun fontDescriptionRun0401;
937   fontDescriptionRun0401.characterRun.characterIndex = 0u;
938   fontDescriptionRun0401.characterRun.numberOfCharacters = 10u;
939   fontDescriptionRun0401.familyLength = fontFamilyHebrew.size();
940   fontDescriptionRun0401.familyName = new char[fontDescriptionRun0401.familyLength];
941   memcpy( fontDescriptionRun0401.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0401.familyLength );
942   fontDescriptionRun0401.familyDefined = true;
943   fontDescriptionRun0401.weightDefined = false;
944   fontDescriptionRun0401.widthDefined = false;
945   fontDescriptionRun0401.slantDefined = false;
946   fontDescriptionRun0401.sizeDefined = false;
947
948   FontDescriptionRun fontDescriptionRun0402;
949   fontDescriptionRun0402.characterRun.characterIndex = 10u;
950   fontDescriptionRun0402.characterRun.numberOfCharacters = 12u;
951   fontDescriptionRun0402.familyLength = fontFamily.size();
952   fontDescriptionRun0402.familyName = new char[fontDescriptionRun0402.familyLength];
953   memcpy( fontDescriptionRun0402.familyName, fontFamily.c_str(), fontDescriptionRun0402.familyLength );
954   fontDescriptionRun0402.familyDefined = true;
955   fontDescriptionRun0402.weightDefined = false;
956   fontDescriptionRun0402.widthDefined = false;
957   fontDescriptionRun0402.slantDefined = false;
958   fontDescriptionRun0402.sizeDefined = false;
959
960   FontDescriptionRun fontDescriptionRun0403;
961   fontDescriptionRun0403.characterRun.characterIndex = 22u;
962   fontDescriptionRun0403.characterRun.numberOfCharacters = 10u;
963   fontDescriptionRun0403.familyLength = fontFamilyHebrew.size();
964   fontDescriptionRun0403.familyName = new char[fontDescriptionRun0403.familyLength];
965   memcpy( fontDescriptionRun0403.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0403.familyLength );
966   fontDescriptionRun0403.familyDefined = true;
967   fontDescriptionRun0403.weightDefined = false;
968   fontDescriptionRun0403.widthDefined = false;
969   fontDescriptionRun0403.slantDefined = false;
970   fontDescriptionRun0403.sizeDefined = false;
971
972   FontDescriptionRun fontDescriptionRun0404;
973   fontDescriptionRun0404.characterRun.characterIndex = 32u;
974   fontDescriptionRun0404.characterRun.numberOfCharacters = 24u;
975   fontDescriptionRun0404.familyLength = fontFamily.size();
976   fontDescriptionRun0404.familyName = new char[fontDescriptionRun0404.familyLength];
977   memcpy( fontDescriptionRun0404.familyName, fontFamily.c_str(), fontDescriptionRun0404.familyLength );
978   fontDescriptionRun0404.familyDefined = true;
979   fontDescriptionRun0404.weightDefined = false;
980   fontDescriptionRun0404.widthDefined = false;
981   fontDescriptionRun0404.slantDefined = false;
982   fontDescriptionRun0404.sizeDefined = false;
983
984   FontDescriptionRun fontDescriptionRun0405;
985   fontDescriptionRun0405.characterRun.characterIndex = 56u;
986   fontDescriptionRun0405.characterRun.numberOfCharacters = 10u;
987   fontDescriptionRun0405.familyLength = fontFamilyHebrew.size();
988   fontDescriptionRun0405.familyName = new char[fontDescriptionRun0405.familyLength];
989   memcpy( fontDescriptionRun0405.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0405.familyLength );
990   fontDescriptionRun0405.familyDefined = true;
991   fontDescriptionRun0405.weightDefined = false;
992   fontDescriptionRun0405.widthDefined = false;
993   fontDescriptionRun0405.slantDefined = false;
994   fontDescriptionRun0405.sizeDefined = false;
995
996   Vector<FontDescriptionRun> fontDescriptionRuns04;
997   fontDescriptionRuns04.PushBack( fontDescriptionRun0401 );
998   fontDescriptionRuns04.PushBack( fontDescriptionRun0402 );
999   fontDescriptionRuns04.PushBack( fontDescriptionRun0403 );
1000   fontDescriptionRuns04.PushBack( fontDescriptionRun0404 );
1001   fontDescriptionRuns04.PushBack( fontDescriptionRun0405 );
1002
1003   unsigned int  visualIndex04[] = {  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u,
1004                                     10u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u, 21u,
1005                                     23u, 24u, 25u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 40u, 41u, 42u, 43u, 44u,
1006                                     44u, 45u, 46u, 47u, 48u, 49u, 50u, 51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u };
1007
1008   unsigned int characterIndex04[] = {  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,
1009                                       10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u,
1010                                       22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u, 22u,
1011                                       44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u, 44u };
1012
1013   unsigned int logicalIndex04[] = {  9u,  8u,  7u,  6u,  5u,  4u,  3u,  2u,  1u,  0u,
1014                                     10u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u, 21u,
1015                                     43u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 40u, 41u, 42u, 32u, 31u, 30u, 29u, 28u, 27u, 26u, 25u, 24u, 23u, 22u,
1016                                     44u, 45u, 46u, 47u, 48u, 49u, 50u, 51u, 52u, 53u, 54u, 55u, 56u, 64u, 63u, 62u, 61u, 60u, 59u, 58u, 57u, 65u };
1017
1018   unsigned int bidirectionalLineIndex04[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
1019                                               0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
1020                                               1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
1021                                               2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u };
1022
1023 // LO   A  B  C  D  E  F  G  H  I  J  K
1024 //     0  1  2  3  4  5  6  7  8  9 10 11
1025 // LO   L  M  N
1026 //    11 12 13 14
1027
1028   // Set a known font description
1029   FontDescriptionRun fontDescriptionRun0501;
1030   fontDescriptionRun0501.characterRun.characterIndex = 0u;
1031   fontDescriptionRun0501.characterRun.numberOfCharacters = 14u;
1032   fontDescriptionRun0501.familyLength = fontFamily.size();
1033   fontDescriptionRun0501.familyName = new char[fontDescriptionRun0501.familyLength];
1034   memcpy( fontDescriptionRun0501.familyName, fontFamily.c_str(), fontDescriptionRun0501.familyLength );
1035   fontDescriptionRun0501.familyDefined = true;
1036   fontDescriptionRun0501.weightDefined = false;
1037   fontDescriptionRun0501.widthDefined = false;
1038   fontDescriptionRun0501.slantDefined = false;
1039   fontDescriptionRun0501.sizeDefined = false;
1040
1041   Vector<FontDescriptionRun> fontDescriptionRuns05;
1042   fontDescriptionRuns05.PushBack( fontDescriptionRun0501 );
1043
1044   unsigned int  visualIndex05[] = {  0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u,
1045                                     11u, 12u, 13u, 14u };
1046
1047   unsigned int characterIndex05[] = { 0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,
1048                                       11u, 11u, 11u, 11u };
1049
1050   unsigned int logicalIndex05[] = { 0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u,
1051                                     11u, 12u, 13u, 14u };
1052
1053   unsigned int bidirectionalLineIndex05[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
1054                                               0u, 0u, 0u, 0u };
1055
1056 // LO      ק  ר  א  ט  ו  ן  ם  פ  ש  ד  ג
1057 //        0  1  2  3  4  5  6  7  8  9  10 11
1058 // VO      ג  ד  ש  פ  ם  ן  ו  ט  א  ר  ק
1059
1060 // LO      כ  ע  י  ח  ל
1061 //       11 12 13 14 15 16
1062 // VO      ל  ח  י  ע  כ
1063
1064   // Set a known font description
1065   FontDescriptionRun fontDescriptionRun0601;
1066   fontDescriptionRun0601.characterRun.characterIndex = 0u;
1067   fontDescriptionRun0601.characterRun.numberOfCharacters = 14u;
1068   fontDescriptionRun0601.familyLength = fontFamilyHebrew.size();
1069   fontDescriptionRun0601.familyName = new char[fontDescriptionRun0601.familyLength];
1070   memcpy( fontDescriptionRun0601.familyName, fontFamilyHebrew.c_str(), fontDescriptionRun0601.familyLength );
1071   fontDescriptionRun0601.familyDefined = true;
1072   fontDescriptionRun0601.weightDefined = false;
1073   fontDescriptionRun0601.widthDefined = false;
1074   fontDescriptionRun0601.slantDefined = false;
1075   fontDescriptionRun0601.sizeDefined = false;
1076
1077   Vector<FontDescriptionRun> fontDescriptionRuns06;
1078   fontDescriptionRuns06.PushBack( fontDescriptionRun0601 );
1079
1080   unsigned int  visualIndex06[] = {  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u,
1081                                     11u, 12u, 13u, 14u, 15u, 16u };
1082
1083   unsigned int characterIndex06[] = {  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,  0u,
1084                                       12u, 12u, 12u, 12u, 12u, 12u };
1085
1086   unsigned int logicalIndex06[] = { 11u, 10u,  9u,  8u,  7u,  6u,  5u,  4u,  3u,  2u,  1u,
1087                                     13u, 16u, 15u, 14u, 13u, 12u };
1088
1089   unsigned int bidirectionalLineIndex06[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
1090                                               1u, 1u, 1u, 1u, 1u, 1u };
1091
1092   struct GetLogicalCursorIndexData data[] =
1093   {
1094     {
1095       "Zero characters text",
1096       "",
1097       Size( 300.f, 300.f ),
1098       0u,
1099       nullptr,
1100       1u,
1101       visualIndex01,
1102       characterIndex01,
1103       logicalIndex01,
1104       bidirectionalLineIndex01,
1105     },
1106     {
1107       "All left to right text 01.",
1108       "Hello world\ndemo",
1109       Size( 300.f, 300.f ),
1110       1u,
1111       fontDescriptionRuns02.Begin(),
1112       4u,
1113       visualIndex02,
1114       characterIndex02,
1115       logicalIndex02,
1116       bidirectionalLineIndex02,
1117     },
1118     {
1119       "bidirectional text 01.",
1120       "Hello world\nשלום עולם\nhello world שלום עולם\nשלום עולם hello world\n",
1121       Size( 300.f, 300.f ),
1122       5u,
1123       fontDescriptionRuns03.Begin(),
1124       65u,
1125       visualIndex03,
1126       characterIndex03,
1127       logicalIndex03,
1128       bidirectionalLineIndex03,
1129     },
1130     {
1131       "bidirectional text 02.",
1132       "שלום עולם\nhello world\nשלום עולם hello world\nhello world שלום עולם\n",
1133       Size( 300.f, 300.f ),
1134       5u,
1135       fontDescriptionRuns04.Begin(),
1136       65u,
1137       visualIndex04,
1138       characterIndex04,
1139       logicalIndex04,
1140       bidirectionalLineIndex04,
1141     },
1142     {
1143       "long line 01.",
1144       "ABCDEFGHIJKLMN",
1145       Size( 100.f, 300.f ),
1146       1u,
1147       fontDescriptionRuns05.Begin(),
1148       13u,
1149       visualIndex05,
1150       characterIndex05,
1151       logicalIndex05,
1152       bidirectionalLineIndex05,
1153     },
1154     {
1155       "bidirectional text 03.",
1156       "קראטוןםפשדגכעיחל",
1157       Size( 100.f, 300.f ),
1158       1u,
1159       fontDescriptionRuns06.Begin(),
1160       15u,
1161       visualIndex06,
1162       characterIndex06,
1163       logicalIndex06,
1164       bidirectionalLineIndex06,
1165     },
1166   };
1167   const unsigned int numberOfTests = 6u;
1168
1169   for( unsigned int index = 0u; index < numberOfTests; ++index )
1170   {
1171     ToolkitTestApplication application;
1172     if( !GetLogicalCursorIndexTest( data[index] ) )
1173     {
1174       tet_result(TET_FAIL);
1175     }
1176   }
1177
1178   tet_result(TET_PASS);
1179   END_TEST;
1180 }