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