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