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