[dali_2.1.3] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-Text-Cursor.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/cursor-helper-functions.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 // LineIndex GetClosestLine( VisualModelPtr visualModel,
35 //                           float visualY,
36 //                           bool& isLineHit )
37 // CharacterIndex GetClosestCursorIndex( VisualModelPtr visualModel,
38 //                                       LogicalModelPtr logicalModel,
39 //                                       MetricsPtr metrics,
40 //                                       float visualX,
41 //                                       float visualY,
42 //                                       CharacterHitTest::Mode mode,
43 //                                       bool& isCharacterHit )
44
45 //////////////////////////////////////////////////////////
46
47 namespace
48 {
49   const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
50   const unsigned int DEFAULT_FONT_SIZE = 1152u;
51
52 struct GetClosestLineData
53 {
54   std::string    description;                    ///< Description of the test.
55   std::string    text;                           ///< Input text.
56   unsigned int   numberOfTests;                  ///< The number of tests.
57   float*         visualY;                        ///< The visual 'y' position for each test.
58   LineIndex*     lineIndex;                      ///< The expected line index for each test.
59   bool*          isLineHit;                      ///< The expected line hit value for each test.
60 };
61
62 struct GetClosestCursorIndexData
63 {
64   std::string             description;           ///< Description of the test.
65   std::string             text;                  ///< Input text.
66   unsigned int            numberOfTests;         ///< The number of tests.
67   float*                  visualX;               ///< The visual 'x' position for each test.
68   float*                  visualY;               ///< The visual 'y' position for each test.
69   CharacterHitTest::Mode* mode;                  ///< The type of hit test.
70   CharacterIndex*         logicalIndex;          ///< The expected logical cursor index for each test.
71   bool*                   isCharacterHit;        ///< The expected character hit value for each test.
72 };
73
74 struct GetCursorPositionData
75 {
76   std::string     description;                    ///< Description of the test.
77   std::string     text;                           ///< Input text.
78   unsigned int    numberOfTests;                  ///< The number of tests.
79   CharacterIndex* logicalIndex;                   ///< The logical cursor index for each test.
80   float*          visualX;                        ///< The expected visual 'x' position for each test.
81   float*          visualY;                        ///< The expected visual 'y' position for each test.
82 };
83
84 struct FindSelectionIndicesData
85 {
86   std::string     description;                    ///< Description of the test.
87   std::string     text;                           ///< Input text.
88   unsigned int    numberOfTests;                  ///< The number of tests.
89   float*          visualX;                        ///< The visual 'x' position for each test.
90   float*          visualY;                        ///< The visual 'y' position for each test.
91   bool*           found;                          ///< Whether selection indices are found.
92   CharacterIndex* startIndex;                     ///< The expected start cursor index for each test.
93   CharacterIndex* endIndex;                       ///< The expected end cursor index for each test.
94   CharacterIndex* noTextHitIndex;                 ///< The expected character index when there is no hit.
95 };
96
97 struct PrimaryCursorHeightData
98 {
99   std::string     description;                    ///< Description of the test.
100   std::string     text;                           ///< Input text.
101   unsigned int    numberOfTests;                  ///< The number of tests.
102   CharacterIndex* logicalIndex;                   ///< The logical cursor index for each test.
103   float*          heights;                        ///< The expected primary cursor height for each test.
104 };
105
106 bool GetClosestLineTest( const GetClosestLineData& data )
107 {
108   std::cout << "  testing : " << data.description << std::endl;
109
110   // 1) Create the model.
111   ModelPtr textModel;
112   MetricsPtr metrics;
113   Size textArea(400.f, 600.f);
114   Size layoutSize;
115
116   Vector<FontDescriptionRun> fontDescriptionRuns;
117   LayoutOptions options;
118   CreateTextModel( data.text,
119                    textArea,
120                    fontDescriptionRuns,
121                    options,
122                    layoutSize,
123                    textModel,
124                    metrics,
125                    false,
126                    LineWrap::WORD,
127                    false,
128                    Toolkit::DevelText::EllipsisPosition::END,
129                    0.f );
130
131   LogicalModelPtr logicalModel = textModel->mLogicalModel;
132   VisualModelPtr visualModel = textModel->mVisualModel;
133
134   for( unsigned int index = 0; index < data.numberOfTests; ++index )
135   {
136     bool isLineHit = false;
137     const LineIndex lineIndex = GetClosestLine( visualModel,
138                                                 data.visualY[index],
139                                                 isLineHit );
140
141     if( lineIndex != data.lineIndex[index] )
142     {
143       std::cout << "  test " << index << " failed. Different line index : " << lineIndex << ", expected : " << data.lineIndex[index] << std::endl;
144       return false;
145     }
146     if( isLineHit != data.isLineHit[index] )
147     {
148       std::cout << "  test " << index << " failed. Different line hit value : " << isLineHit << ", expected : " << data.isLineHit[index] << std::endl;
149       return false;
150     }
151   }
152
153   return true;
154 }
155
156 bool GetClosestCursorIndexTest( const GetClosestCursorIndexData& data )
157 {
158   std::cout << "  testing : " << data.description << std::endl;
159
160   // 1) Create the model.
161   ModelPtr textModel;
162   MetricsPtr metrics;
163   Size textArea(400.f, 600.f);
164   Size layoutSize;
165
166   Vector<FontDescriptionRun> fontDescriptionRuns;
167   LayoutOptions options;
168   CreateTextModel( data.text,
169                    textArea,
170                    fontDescriptionRuns,
171                    options,
172                    layoutSize,
173                    textModel,
174                    metrics,
175                    false,
176                    LineWrap::WORD,
177                    false,
178                    Toolkit::DevelText::EllipsisPosition::END,
179                    0.f );
180
181   LogicalModelPtr logicalModel = textModel->mLogicalModel;
182   VisualModelPtr visualModel = textModel->mVisualModel;
183
184   for( unsigned int index = 0; index < data.numberOfTests; ++index )
185   {
186     bool isCharacterHit = false;
187     const CharacterIndex logicalCursorIndex = GetClosestCursorIndex( visualModel,
188                                                                      logicalModel,
189                                                                      metrics,
190                                                                      data.visualX[index],
191                                                                      data.visualY[index],
192                                                                      data.mode[index],
193                                                                      isCharacterHit );
194
195     if( logicalCursorIndex != data.logicalIndex[index] )
196     {
197       std::cout << "  test " << index << " failed. Different logical cursor index : " << logicalCursorIndex << ", expected : " << data.logicalIndex[index] << std::endl;
198       return false;
199     }
200     if( isCharacterHit != data.isCharacterHit[index] )
201     {
202       std::cout << "  test " << index << " failed. Different character hit value : " << isCharacterHit << ", expected : " << data.isCharacterHit[index] << std::endl;
203       return false;
204     }
205   }
206
207   return true;
208 }
209
210 bool GetCursorPositionTest( const GetCursorPositionData& data )
211 {
212   std::cout << "  testing : " << data.description << std::endl;
213
214   // 1) Create the model.
215   ModelPtr textModel;
216   MetricsPtr metrics;
217   Size textArea(400.f, 600.f);
218   Size layoutSize;
219
220   Vector<FontDescriptionRun> fontDescriptionRuns;
221   LayoutOptions options;
222   CreateTextModel( data.text,
223                    textArea,
224                    fontDescriptionRuns,
225                    options,
226                    layoutSize,
227                    textModel,
228                    metrics,
229                    false,
230                    LineWrap::WORD,
231                    false,
232                    Toolkit::DevelText::EllipsisPosition::END,
233                    0.f );
234
235   LogicalModelPtr logicalModel = textModel->mLogicalModel;
236   VisualModelPtr visualModel = textModel->mVisualModel;
237
238   GetCursorPositionParameters parameters;
239   parameters.visualModel = visualModel;
240   parameters.logicalModel = logicalModel;
241   parameters.metrics = metrics;
242   parameters.isMultiline = true;
243
244   for( unsigned int index = 0; index < data.numberOfTests; ++index )
245   {
246     CursorInfo cursorInfo;
247     parameters.logical = data.logicalIndex[index];
248
249     GetCursorPosition( parameters,
250                        0.f,// Since this test case is not testing the primary cursor height, the default font line height can be set to 0.f.
251                        cursorInfo );
252
253     if( floor(cursorInfo.primaryPosition.x) != data.visualX[index] )
254     {
255       std::cout << "  test " << index << " failed. Different 'x' cursor position : " << cursorInfo.primaryPosition.x << ", expected : " << data.visualX[index] << std::endl;
256       return false;
257     }
258     if( floor(cursorInfo.primaryPosition.y) != data.visualY[index] )
259     {
260       std::cout << "  test " << index << " failed. Different 'y' cursor position : " << cursorInfo.primaryPosition.y << ", expected : " << data.visualY[index] << std::endl;
261       return false;
262     }
263   }
264
265   return true;
266 }
267
268 bool FindSelectionIndicesTest( const FindSelectionIndicesData& data )
269 {
270   std::cout << "  testing : " << data.description << std::endl;
271
272   // 1) Create the model.
273   ModelPtr textModel;
274   MetricsPtr metrics;
275   Size textArea(400.f, 600.f);
276   Size layoutSize;
277
278   Vector<FontDescriptionRun> fontDescriptionRuns;
279   LayoutOptions options;
280   CreateTextModel( data.text,
281                    textArea,
282                    fontDescriptionRuns,
283                    options,
284                    layoutSize,
285                    textModel,
286                    metrics,
287                    false,
288                    LineWrap::WORD,
289                    false,
290                    Toolkit::DevelText::EllipsisPosition::END,
291                    0.f );
292
293   LogicalModelPtr logicalModel = textModel->mLogicalModel;
294   VisualModelPtr visualModel = textModel->mVisualModel;
295
296   for( unsigned int index = 0; index < data.numberOfTests; ++index )
297   {
298     CharacterIndex startIndex = 0;
299     CharacterIndex endIndex = 0;
300     CharacterIndex noTextHitIndex = 0;
301     const bool found = FindSelectionIndices( visualModel,
302                                              logicalModel,
303                                              metrics,
304                                              data.visualX[index],
305                                              data.visualY[index],
306                                              startIndex,
307                                              endIndex,
308                                              noTextHitIndex );
309
310     if( found != data.found[index] )
311     {
312       std::cout << "  test " << index << " failed. Different found value : " << found << ", expected : " <<  data.found[index] << std::endl;
313       return false;
314     }
315     if( startIndex != data.startIndex[index] )
316     {
317       std::cout << "  test " << index << " failed. Different start index : " << startIndex << ", expected : " << data.startIndex[index] << std::endl;
318       return false;
319     }
320     if( endIndex != data.endIndex[index] )
321     {
322       std::cout << "  test " << index << " failed. Different end index : " << endIndex << ", expected : " << data.endIndex[index] << std::endl;
323       return false;
324     }
325     if( noTextHitIndex != data.noTextHitIndex[index] )
326     {
327       std::cout << "  test " << index << " failed. Different no text hit index : " << noTextHitIndex << ", expected : " << data.noTextHitIndex[index] << std::endl;
328       return false;
329     }
330   }
331   return true;
332 }
333
334 bool PrimaryCursorHeightTest( const PrimaryCursorHeightData& data )
335 {
336   std::cout << "  testing : " << data.description << std::endl;
337
338   // 1) Create the model.
339   ModelPtr textModel;
340   MetricsPtr metrics;
341   Size textArea(400.f, 600.f);
342   Size layoutSize;
343
344   Vector<FontDescriptionRun> fontDescriptionRuns;
345
346   const std::string fontFamily( "DejaVuSans" );
347
348   // Set a known font description
349   FontDescriptionRun fontDescriptionRun1;
350   fontDescriptionRun1.characterRun.characterIndex = 0u;
351   fontDescriptionRun1.characterRun.numberOfCharacters = 13u;
352   fontDescriptionRun1.familyLength = fontFamily.size();
353   fontDescriptionRun1.familyName = new char[fontDescriptionRun1.familyLength];
354   memcpy( fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength );
355   fontDescriptionRun1.familyDefined = true;
356   fontDescriptionRun1.weightDefined = false;
357   fontDescriptionRun1.widthDefined = false;
358   fontDescriptionRun1.slantDefined = false;
359   fontDescriptionRun1.sizeDefined = true;
360   fontDescriptionRun1.size = 768u;//Font size = 12.0f (768/64 = 12)
361
362   fontDescriptionRuns.PushBack( fontDescriptionRun1 );
363
364   LayoutOptions options;
365   CreateTextModel( data.text,
366                    textArea,
367                    fontDescriptionRuns,
368                    options,
369                    layoutSize,
370                    textModel,
371                    metrics,
372                    false,
373                    LineWrap::WORD,
374                    false,
375                    Toolkit::DevelText::EllipsisPosition::END,
376                    50.f );
377
378   LogicalModelPtr logicalModel = textModel->mLogicalModel;
379   VisualModelPtr visualModel = textModel->mVisualModel;
380
381   GetCursorPositionParameters parameters;
382   parameters.visualModel = visualModel;
383   parameters.logicalModel = logicalModel;
384   parameters.metrics = metrics;
385   parameters.isMultiline = true;
386
387   for( unsigned int index = 0; index < data.numberOfTests; ++index )
388   {
389     CursorInfo cursorInfo;
390     parameters.logical = data.logicalIndex[index];
391
392     // Load some fonts.
393     TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
394     fontClient.SetDpi( 93u, 93u );
395
396     char* pathNamePtr = get_current_dir_name();
397     const std::string pathName( pathNamePtr );
398     free( pathNamePtr );
399
400     FontId fontID = fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf" );
401
402     Text::FontMetrics fontMetrics;
403     MetricsPtr mMetrics = Metrics::New(fontClient);
404     mMetrics->GetFontMetrics(fontID, fontMetrics);
405     float defaultFontLineHeight = (fontMetrics.ascender - fontMetrics.descender);
406
407     GetCursorPosition( parameters,
408                        defaultFontLineHeight,
409                        cursorInfo );
410
411     if( floor(cursorInfo.primaryCursorHeight) != data.heights[index] )
412     {
413       std::cout << "  test " << index << " failed. Different primaryCursorHeight : " << cursorInfo.primaryCursorHeight << ", expected : " << data.heights[index] << std::endl;
414       return false;
415     }
416   }
417
418   return true;
419 }
420
421 } // namespace
422
423 //////////////////////////////////////////////////////////
424 //
425 // UtcDaliGetClosestLine
426 // UtcDaliGetClosestCursorIndex
427 // UtcDaliGetCursorPosition
428 // UtcDaliFindSelectionIndices
429 // UtcDaliPrimaryCursorHeight
430 //
431 //////////////////////////////////////////////////////////
432
433 int UtcDaliGetClosestLine(void)
434 {
435   tet_infoline(" UtcDaliGetClosestLine");
436
437   float visualY01[] = { -4.f, 3.f, 1000.f };
438   LineIndex lineIndices01[] = { 0, 0, 0 };
439   bool isLineHit01[] = { false, false, false };
440
441   float visualY02[] = { -4.f, 3.f, 1000.f };
442   LineIndex lineIndices02[] = { 0, 0, 0 };
443   bool isLineHit02[] = { false, true, false };
444
445   float visualY03[] = { -4.f, 11.f, 30.f, 51.f, 68.f, 87.f, 109.f, 130.f };
446   LineIndex lineIndices03[] = { 0, 0, 1u, 2u, 3u, 4u, 5u, 5u };
447   bool isLineHit03[] = { false, true, true, true, true, true, true, false };
448
449   struct GetClosestLineData data[] =
450   {
451     {
452       "void text.",
453       "",
454       3u,
455       visualY01,
456       lineIndices01,
457       isLineHit01
458     },
459     {
460       "Single line text.",
461       "hello world",
462       3u,
463       visualY02,
464       lineIndices02,
465       isLineHit02
466     },
467     {
468       "Multi-line text.",
469       "abcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuדאוvwxה"
470       "סתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuד"
471       "אוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqr"
472       "פרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmno"
473       "צמםpqrפרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjkl"
474       "חלךmnoצמםpqrפרףstuדאוvwxהסתyzטזץ",
475       8u,
476       visualY03,
477       lineIndices03,
478       isLineHit03
479     }
480   };
481   const unsigned int numberOfTests = 3u;
482
483   for( unsigned int index = 0; index < numberOfTests; ++index )
484   {
485     ToolkitTestApplication application;
486     if( !GetClosestLineTest( data[index] ) )
487     {
488       tet_result(TET_FAIL);
489     }
490   }
491
492   tet_result(TET_PASS);
493   END_TEST;
494 }
495
496 int UtcDaliGetClosestCursorIndex(void)
497 {
498   tet_infoline(" UtcDaliGetClosestCursorIndex");
499
500   float visualX01[] = { -100.f };
501   float visualY01[] = { -100.f };
502   CharacterHitTest::Mode mode01[] = { CharacterHitTest::TAP };
503   CharacterIndex logicalIndex01[] = { 0 };
504   bool isCharacterHit01[] = { false };
505
506   float visualX02[] = { -100.f, 1000.f, 60.f, 79.f, 83.f, 148.f, 99.f };
507   float visualY02[] = { -100.f, 1000.f, 12.f, 12.f, 12.f, 12.f, 12.f };
508   CharacterHitTest::Mode mode02[] = { CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP };
509   CharacterIndex logicalIndex02[] = { 0, 21u, 7u, 10u, 10u, 14u, 12u };
510   bool isCharacterHit02[] = { false, false, true, true, true, true, true  };
511
512   float visualX03[] = { 19.f, 104.f, -2.f, 127.f };
513   float visualY03[] = { 12.f, 12.f, 12.f, 12.f };
514   CharacterHitTest::Mode mode03[] = { CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP };
515   CharacterIndex logicalIndex03[] = { 3u, 13u, 0, 18u };
516   bool isCharacterHit03[] = { true, true, false, false };
517
518   //  0     5 _ 6     11  12
519   //   Hello     world  \n
520   // 12    16 _ 17    21   22
521   //   שלום       עולם  \n
522   // 22         31_32      40  41
523   //   different     الأربعاء  \n
524   float visualX04[] = { -100.f, 40.f, 44.f, 85.f, 500.f,
525                          500.f, 367.f, 359.f, 329.f, -100.f,
526                         -100.f, 19.f, 64.f, 72.f, 104.f, 111.f, 500.f};
527   float visualY04[] = { -100.f, 12.f, 12.f, 12.f, 12.f,
528                           30.f, 30.f, 30.f, 30.f, 30.f,
529                           50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f };
530   CharacterHitTest::Mode mode04[] = { CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
531                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
532                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP };
533   CharacterIndex logicalIndex04[] = {    0,  5u,  6u, 11u, 11u,
534                                        12u, 16u, 17u, 21u, 21u,
535                                        22u, 25u, 30u, 32u, 35u, 34u, 40u,
536                                        41u };
537   bool isCharacterHit04[] = { false, true, true, true, false,
538                               false, true, true, true, false,
539                               false, true, true, true, true, true, false };
540
541   //   0           10           20            30           40      46
542   //    abcשנבdefג   קכghiעיןjk   lחלךmnoצמם   pqrפרףstuד   אוvwxה
543   //  46     50            60            70           80               93
544   //    סתyz   טזץabcשנבd    efגקכghiעי    ןjklחלךmno   צמםpqrפרףstuד
545   //  93       100           110          120         130          139
546   //    אוvwxהס   תyzטזץabcש   נבdefגקכgh   iעיןjklחלך   mnoצמםpqr
547   // 139           150           160           170          180       186
548   //    פרףstuדאוvw   xהסתyzטזץa   bcשנבdefגק    כghiעיןjkl    חלךmno
549   // 186     190           200           210          220            233
550   //    צמםp   qrפרףstuדא    וvwxהסתyzט   זץabcשנבde   fגקכghiעיןjkl
551   // 233        240            250           260     265
552   //    חלךmnoצ    מםpqrפרףst   uדאוvwxהסת    yzטזץ
553
554   float visualX05[] = { -100.f, 96.f, 155.f, 250.f, 344.f, 500.f,
555                         -100.f, 36.f, 124.f, 190.f, 280.f, 500.f,
556                         -100.f, 56.f, 158.f, 237.f, 303.f, 500.f,
557                         -100.f, 98.f, 184.f, 261.f, 337.f, 500.f,
558                         -100.f, 40.f, 113.f, 223.f, 302.f, 500.f,
559                         -100.f, 82.f, 160.f, 253.f, 500.f };
560   float visualY05[] = { -100.f, 12.f, 12.f, 12.f, 12.f, 12.f,
561                         30.f, 30.f, 30.f, 30.f, 30.f, 30.f,
562                         50.f, 50.f, 50.f, 50.f, 50.f, 50.f,
563                         67.f, 67.f, 67.f, 67.f, 67.f, 67.f,
564                         87.f, 87.f, 87.f, 87.f, 87.f, 87.f,
565                         107.f, 107.f, 107.f, 107.f, 107.f };
566   CharacterHitTest::Mode mode05[] = { CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
567                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
568                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
569                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
570                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
571                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP };
572   CharacterIndex logicalIndex05[] = {    0,  10u,  19u,  28u,  39u,  44u,
573                                        45u,  48u,  59u,  66u,  78u,  87u,
574                                        89u,  96u, 106u, 115u, 124u, 133u,
575                                       134u, 145u, 154u, 162u, 171u, 179u,
576                                       180u, 184u, 191u, 203u, 212u,
577                                       221u, 222u, 233u, 241u, 251u, 265u };
578   bool isCharacterHit05[] = { false, true, true, true, true, false,
579                               false, true, true, true, true, false,
580                               false, true, true, true, true, false,
581                               false, true, true, true, true, false,
582                               false, true, true, true, true, false,
583                               false, true, true, true, false };
584
585   //   0            10           20           30           40        46
586   //    שנבabcגקכd    efעיןghiחל   ךjklצמםmno   פרףpqrדאוs   tuהסתv
587   //  46     50           60          70            80              93
588   //    wxטז   ץyzשנבabcג   קכdefעיןgh   iחלךjklצמם   mnoפרףpqrדאוs
589   //  93        100          110          120           130           139
590   //    tuהסתvw   xטזץyzשנבa   bcגקכdefעי    ןghiחלךjkl    צמםmnoפרף
591   // 139           150           160          170         180       186
592   //    pqrדאוstuהס   תvwxטזץyzש   נבabcגקכde   fעיןghiחלך   jklצמם
593   // 186    190          200           210           220            232
594   //    mnoפ   רףpqrדאוst   uהסתvwxטזץ   yzשנבabcגק    כdefעיןghiחל
595   // 232         240           250           260     265
596   //    ךjklצמםm   noפרףpqrדא    וstuהסתvwx   טזץyz
597
598   float visualX06[] = { 500.f, 307.f, 237.f, 148.f, 55.f, -100.f,
599                         500.f, 362.f, 276.f, 213.f, 121.f, -100.f,
600                         500.f, 344.f, 238.f, 167.f, 93.f, -100.f,
601                         500.f, 306.f, 216.f, 142.f, 58.f, -100.f,
602                         500.f, 355.f, 279.f, 182.f, 92.f, -100.f,
603                         500.f, 326.f, 238.f, 150.f, -100.f };
604   float visualY06[] = { -100.f, 12.f, 12.f, 12.f, 12.f, 12.f,
605                         30.f, 30.f, 30.f, 30.f, 30.f, 30.f,
606                         50.f, 50.f, 50.f, 50.f, 50.f, 50.f,
607                         67.f, 67.f, 67.f, 67.f, 67.f, 67.f,
608                         87.f, 87.f, 87.f, 87.f, 87.f, 87.f,
609                         107.f, 107.f, 107.f, 107.f, 107.f };
610   CharacterHitTest::Mode mode06[] = { CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
611                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
612                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
613                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
614                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
615                                       CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP };
616   CharacterIndex logicalIndex06[] = {    0,  11u,  19u,  28u,  39u,  44u,
617                                        45u,  48u,  57u,  65u,  78u,  87u,
618                                        89u,  96u, 107u, 114u, 124u, 133u,
619                                       134u, 144u, 154u, 162u, 171u, 178u,
620                                       179u, 185u, 192u, 203u, 212u, 221u,
621                                       222u, 232u, 240u, 251u, 265u  };
622   bool isCharacterHit06[] = { false, true, true, true, true, false,
623                               false, true, true, true, true, false,
624                               false, true, true, true, true, false,
625                               false, true, true, true, true, false,
626                               false, true, true, true, true, false,
627                               false, true, true, true, false };
628
629   float visualX07[] = { 395.f };
630   float visualY07[] = { 12.f };
631   CharacterHitTest::Mode mode07[] = { CharacterHitTest::TAP };
632   CharacterIndex logicalIndex07[] = { 1u };
633   bool isCharacterHit07[] = { true };
634
635   float visualX08[] = { 7.f };
636   float visualY08[] = { 12.f };
637   CharacterHitTest::Mode mode08[] = { CharacterHitTest::TAP };
638   CharacterIndex logicalIndex08[] = { 1u };
639   bool isCharacterHit08[] = { true };
640
641   struct GetClosestCursorIndexData data[] =
642   {
643     {
644       "Void text.",
645       "",
646       1u,
647       visualX01,
648       visualY01,
649       mode01,
650       logicalIndex01,
651       isCharacterHit01
652     },
653     {
654       "Single line text.",
655       "Hello world שלום עולם",
656       7u,
657       visualX02,
658       visualY02,
659       mode02,
660       logicalIndex02,
661       isCharacterHit02
662     },
663     {
664       "Single line with ligatures",
665       "different الأربعاء",
666       4u,
667       visualX03,
668       visualY03,
669       mode03,
670       logicalIndex03,
671       isCharacterHit03
672     },
673     {
674       "Multiline. Single line paragraphs",
675       "Hello world\n"
676       "שלום עולם\n"
677       "different الأربعاء\n",
678       17u,
679       visualX04,
680       visualY04,
681       mode04,
682       logicalIndex04,
683       isCharacterHit04
684     },
685     {
686       "Multiline. Single bidirectional paragraph, starts LTR, wrapped lines",
687       "abcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuדאוvwxה"
688       "סתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuד"
689       "אוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqr"
690       "פרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmno"
691       "צמםpqrפרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjkl"
692       "חלךmnoצמםpqrפרףstuדאוvwxהסתyzטזץ",
693       35u,
694       visualX05,
695       visualY05,
696       mode05,
697       logicalIndex05,
698       isCharacterHit05
699     },
700     {
701       "Multiline. Single bidirectional paragraph, starts RTL, wrapped lines",
702       "שנבabcגקכdefעיןghiחלךjklצמםmnoפרףpqrדאוstuהסתv"
703       "wxטזץyzשנבabcגקכdefעיןghiחלךjklצמםmnoפרףpqrדאוs"
704       "tuהסתvwxטזץyzשנבabcגקכdefעיןghiחלךjklצמםmnoפרף"
705       "pqrדאוstuהסתvwxטזץyzשנבabcגקכdefעיןghiחלךjklצמם"
706       "mnoפרףpqrדאוstuהסתvwxטזץyzשנבabcגקכdefעיןghiחל"
707       "ךjklצמםmnoפרףpqrדאוstuהסתvwxטזץyz",
708       35u,
709       visualX06,
710       visualY06,
711       mode06,
712       logicalIndex06,
713       isCharacterHit06
714     },
715     {
716       "Testing complex characters. Arabic ligatures",
717       "الأَبْجَدِيَّة العَرَبِيَّة",
718       1u,
719       visualX07,
720       visualY07,
721       mode07,
722       logicalIndex07,
723       isCharacterHit07
724     },
725     {
726       "Testing complex characters. Latin ligatures",
727       "fi ligature",
728       1u,
729       visualX08,
730       visualY08,
731       mode08,
732       logicalIndex08,
733       isCharacterHit08
734     }
735   };
736   const unsigned int numberOfTests = 8u;
737
738   for( unsigned int index = 0; index < numberOfTests; ++index )
739   {
740     ToolkitTestApplication application;
741     if( !GetClosestCursorIndexTest( data[index] ) )
742     {
743       tet_result(TET_FAIL);
744     }
745   }
746
747   tet_result(TET_PASS);
748   END_TEST;
749 }
750
751 int UtcDaliGetCursorPosition(void)
752 {
753   tet_infoline(" UtcDaliGetCursorPosition");
754
755   float visualX08[] = { 5.f };
756   float visualY08[] = { 0.f };
757   CharacterIndex logicalIndex08[] = { 1u };
758
759   struct GetCursorPositionData data[] =
760   {
761     {
762       "Testing complex characters. Latin ligatures",
763       "fi ligature",
764       1u,
765       logicalIndex08,
766       visualX08,
767       visualY08,
768     }
769   };
770   const unsigned int numberOfTests = 1u;
771
772   for( unsigned int index = 0; index < numberOfTests; ++index )
773   {
774     ToolkitTestApplication application;
775     if( !GetCursorPositionTest( data[index] ) )
776     {
777       tet_result(TET_FAIL);
778     }
779   }
780
781   tet_result(TET_PASS);
782   END_TEST;
783 }
784
785 int UtcDaliFindSelectionIndices(void)
786 {
787   tet_infoline(" UtcDaliFindSelectionIndices");
788
789   float visualX01[] = { -100.f };
790   float visualY01[] = { -100.f };
791   bool found01[] = { false };
792   CharacterIndex startIndex01[] = { 0 };
793   CharacterIndex endIndex01[] = { 0 };
794   CharacterIndex noHitText01[] = { 0 };
795
796   float visualX02[] = { -100.f, 1000.f, 1000.f };
797   float visualY02[] = { -100.f, 12.f, 1000.f };
798   bool found02[] = { false, false, false };
799   CharacterIndex startIndex02[] = { 0, 6u, 6u };
800   CharacterIndex endIndex02[] = { 5u, 11u, 11u };
801   CharacterIndex noHitText02[] = { 0, 11u, 11u };
802
803   float visualX03[] = { 70.f };
804   float visualY03[] = { 12.f };
805   bool found03[] = { true };
806   CharacterIndex startIndex03[] = { 6u };
807   CharacterIndex endIndex03[] = { 11u };
808   CharacterIndex noHitText03[] = { 0u };
809
810   float visualX04[] = { 131.f };
811   float visualY04[] = { 12.f };
812   bool found04[] = { true };
813   CharacterIndex startIndex04[] = { 12u };
814   CharacterIndex endIndex04[] = { 16u };
815   CharacterIndex noHitText04[] = { 0u };
816
817   float visualX05[] = { 0.f };
818   float visualY05[] = { 12.f };
819   bool found05[] = { true };
820   CharacterIndex startIndex05[] = { 0 };
821   CharacterIndex endIndex05[] = { 1u };
822   CharacterIndex noHitText05[] = { 0 };
823
824   float visualX06[] = { 10.f };
825   float visualY06[] = { 12.f };
826   bool found06[] = { true };
827   CharacterIndex startIndex06[] = { 0 };
828   CharacterIndex endIndex06[] = { 1u };
829   CharacterIndex noHitText06[] = { 0u };
830
831   struct FindSelectionIndicesData data[] =
832   {
833     {
834       "void text",
835       "",
836       1u,
837       visualX01,
838       visualY01,
839       found01,
840       startIndex01,
841       endIndex01,
842       noHitText01
843     },
844     {
845       "touch out of text's boundaries",
846       "Hello world",
847       3u,
848       visualX02,
849       visualY02,
850       found02,
851       startIndex02,
852       endIndex02,
853       noHitText02
854     },
855     {
856       "touch on the text",
857       "Hello world demo",
858       1u,
859       visualX03,
860       visualY03,
861       found03,
862       startIndex03,
863       endIndex03,
864       noHitText03
865     },
866     {
867       "touch on the new paragraph character at the end of line",
868       "Hello world demo\n",
869       1u,
870       visualX04,
871       visualY04,
872       found04,
873       startIndex04,
874       endIndex04,
875       noHitText04
876     },
877     {
878       "touch on a white space character. is the unique character of the line",
879       " ",
880       1u,
881       visualX05,
882       visualY05,
883       found05,
884       startIndex05,
885       endIndex05,
886       noHitText05
887     },
888     {
889       "touch on a white space character. is between two words",
890       "h ello",
891       1u,
892       visualX06,
893       visualY06,
894       found06,
895       startIndex06,
896       endIndex06,
897       noHitText06
898     },
899   };
900   const unsigned int numberOfTests = 6u;
901
902   for( unsigned int index = 0; index < numberOfTests; ++index )
903   {
904     ToolkitTestApplication application;
905     if( !FindSelectionIndicesTest( data[index] ) )
906     {
907       tet_result(TET_FAIL);
908     }
909   }
910
911   tet_result(TET_PASS);
912   END_TEST;
913 }
914
915 int UtcDaliPrimaryCursorHeight(void)
916 {
917   tet_infoline(" UtcDaliPrimaryCursorHeight");
918
919   float heights[] = { 19.f };
920   CharacterIndex logicalIndex[] = { 1u };
921
922   struct PrimaryCursorHeightData data[] =
923   {
924     {
925       "Testing primary cursor height when line spacing is used.",
926       "Hello World",
927       1u,
928       logicalIndex,
929       heights,
930     }
931   };
932   const unsigned int numberOfTests = 1u;
933
934   for( unsigned int index = 0; index < numberOfTests; ++index )
935   {
936     ToolkitTestApplication application;
937     if( !PrimaryCursorHeightTest( data[index] ) )
938     {
939       tet_result(TET_FAIL);
940     }
941   }
942
943   tet_result(TET_PASS);
944   END_TEST;
945 }