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