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