1755b8be39295750e85499e725855607b1138d3b
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-Text-Cursor.cpp
1 /*
2  * Copyright (c) 2016 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 // CharacterIndex GetClosestCursorIndex( VisualModelPtr visualModel,
37 //                                       LogicalModelPtr logicalModel,
38 //                                       MetricsPtr metrics,
39 //                                       float visualX,
40 //                                       float visualY )
41
42 //////////////////////////////////////////////////////////
43
44 namespace
45 {
46
47 struct GetClosestLineData
48 {
49   std::string    description;                    ///< Description of the test.
50   std::string    text;                           ///< Input text.
51   unsigned int   numberOfTests;                  ///< The number of tests.
52   float*         visualY;                        ///< The visual 'y' position for each test.
53   LineIndex*     lineIndex;                      ///< The expected line index for each test.
54 };
55
56 struct GetClosestCursorIndexData
57 {
58   std::string     description;                    ///< Description of the test.
59   std::string     text;                           ///< Input text.
60   unsigned int    numberOfTests;                  ///< The number of tests.
61   float*          visualX;                        ///< The visual 'x' position for each test.
62   float*          visualY;                        ///< The visual 'y' position for each test.
63   CharacterIndex* logicalIndex;                   ///< The expected logical cursor index for each test.
64 };
65
66 bool GetClosestLineTest( const GetClosestLineData& data )
67 {
68   std::cout << "  testing : " << data.description << std::endl;
69
70   // 1) Create the model.
71   LogicalModelPtr logicalModel;
72   VisualModelPtr visualModel;
73   MetricsPtr metrics;
74   Size textArea(400.f, 600.f);
75   Size layoutSize;
76
77   Vector<FontDescriptionRun> fontDescriptionRuns;
78   LayoutOptions options;
79   CreateTextModel( data.text,
80                    textArea,
81                    fontDescriptionRuns,
82                    options,
83                    layoutSize,
84                    logicalModel,
85                    visualModel,
86                    metrics );
87
88   for( unsigned int index = 0u; index < data.numberOfTests; ++index )
89   {
90     const LineIndex lineIndex = GetClosestLine( visualModel,
91                                                 data.visualY[index] );
92
93     if( lineIndex != data.lineIndex[index] )
94     {
95       std::cout << "  test " << index << " failed. Different line index : " << lineIndex << ", expected : " << data.lineIndex[index] << std::endl;
96       return false;
97     }
98   }
99
100   return true;
101 }
102
103 bool GetClosestCursorIndexTest( const GetClosestCursorIndexData& data )
104 {
105   std::cout << "  testing : " << data.description << std::endl;
106
107   // 1) Create the model.
108   LogicalModelPtr logicalModel;
109   VisualModelPtr visualModel;
110   MetricsPtr metrics;
111   Size textArea(400.f, 600.f);
112   Size layoutSize;
113
114   Vector<FontDescriptionRun> fontDescriptionRuns;
115   LayoutOptions options;
116   CreateTextModel( data.text,
117                    textArea,
118                    fontDescriptionRuns,
119                    options,
120                    layoutSize,
121                    logicalModel,
122                    visualModel,
123                    metrics );
124
125   for( unsigned int index = 0u; index < data.numberOfTests; ++index )
126   {
127     const CharacterIndex logicalCursorIndex = GetClosestCursorIndex( visualModel,
128                                                                      logicalModel,
129                                                                      metrics,
130                                                                      data.visualX[index],
131                                                                      data.visualY[index] );
132
133     if( logicalCursorIndex != data.logicalIndex[index] )
134     {
135       std::cout << "  test " << index << " failed. Different logical cursor index : " << logicalCursorIndex << ", expected : " << data.logicalIndex[index] << std::endl;
136       return false;
137     }
138   }
139
140   return true;
141 }
142
143 } // namespace
144
145 //////////////////////////////////////////////////////////
146 //
147 // UtcDaliGetClosestLine
148 // UtcDaliGetClosestCursorIndex
149 //
150 //////////////////////////////////////////////////////////
151
152 int UtcDaliGetClosestLine(void)
153 {
154   tet_infoline(" UtcDaliGetClosestLine");
155
156   float visualY01[] = { -4.f, 3.f, 1000.f };
157   LineIndex lineIndices01[] = { 0u, 0u, 0u };
158
159   float visualY02[] = { -4.f, 3.f, 1000.f };
160   LineIndex lineIndices02[] = { 0u, 0u, 0u };
161
162   float visualY03[] = { -4.f, 11.f, 30.f, 51.f, 68.f, 87.f, 109.f, 130.f };
163   LineIndex lineIndices03[] = { 0u, 0u, 1u, 2u, 3u, 4u, 5u, 5u };
164
165   struct GetClosestLineData data[] =
166   {
167     {
168       "void text.",
169       "",
170       3u,
171       visualY01,
172       lineIndices01,
173     },
174     {
175       "Single line text.",
176       "hello world",
177       3u,
178       visualY02,
179       lineIndices02,
180     },
181     {
182       "Multi-line text.",
183       "abcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuדאוvwxה"
184       "סתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuד"
185       "אוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqr"
186       "פרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmno"
187       "צמםpqrפרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjkl"
188       "חלךmnoצמםpqrפרףstuדאוvwxהסתyzטזץ",
189       8u,
190       visualY03,
191       lineIndices03
192     }
193   };
194   const unsigned int numberOfTests = 3u;
195
196   for( unsigned int index = 0u; index < numberOfTests; ++index )
197   {
198     ToolkitTestApplication application;
199     if( !GetClosestLineTest( data[index] ) )
200     {
201       tet_result(TET_FAIL);
202     }
203   }
204
205   tet_result(TET_PASS);
206   END_TEST;
207 }
208
209 int UtcDaliGetClosestCursorIndex(void)
210 {
211   tet_infoline(" UtcDaliGetClosestCursorIndex");
212   float visualX01[] = { -100.f };
213   float visualY01[] = { -100.f };
214   CharacterIndex logicalIndex01[] = { 0u };
215
216   float visualX02[] = { -100.f, 1000.f, 60.f, 79.f, 83.f, 148.f, 99.f };
217   float visualY02[] = { -100.f, 1000.f, 12.f, 12.f, 12.f, 12.f, 12.f };
218   CharacterIndex logicalIndex02[] = { 0u, 21u, 7u, 10u, 11u, 13u, 20u };
219
220   float visualX03[] = { 19.f, 104.f, -2.f, 127.f };
221   float visualY03[] = { 12.f, 12.f, 12.f, 12.f };
222   CharacterIndex logicalIndex03[] = { 3u, 12u, 0u, 18u };
223
224   //  0     5 _ 6     11  12
225   //   Hello     world  \n
226   // 12    16 _ 17    21   22
227   //   שלום       עולם  \n
228   // 22         31_32      40  41
229   //   different     الأربعاء  \n
230   float visualX04[] = { -100.f, 40.f, 44.f, 85.f, 500.f,
231                          500.f, 367.f, 359.f, 329.f, -100.f,
232                         -100.f, 19.f, 64.f, 72.f, 104.f, 111.f, 500.f};
233   float visualY04[] = { -100.f, 12.f, 12.f, 12.f, 12.f,
234                           30.f, 30.f, 30.f, 30.f, 30.f,
235                           50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f };
236   CharacterIndex logicalIndex04[] = {  0u,  5u,  6u, 11u, 11u,
237                                        12u, 16u, 17u, 21u, 21u,
238                                        22u, 25u, 31u, 32u, 34u, 40u, 40u,
239                                        41u };
240
241   //   0           10           20            30           40      46
242   //    abcשנבdefג   קכghiעיןjk   lחלךmnoצמם   pqrפרףstuד   אוvwxה
243   //  46     50            60            70           80               93
244   //    סתyz   טזץabcשנבd    efגקכghiעי    ןjklחלךmno   צמםpqrפרףstuד
245   //  93       100           110          120         130          139
246   //    אוvwxהס   תyzטזץabcש   נבdefגקכgh   iעיןjklחלך   mnoצמםpqr
247   // 139           150           160           170          180       186
248   //    פרףstuדאוvw   xהסתyzטזץa   bcשנבdefגק    כghiעיןjkl    חלךmno
249   // 186     190           200           210          220            233
250   //    צמםp   qrפרףstuדא    וvwxהסתyzט   זץabcשנבde   fגקכghiעיןjkl
251   // 233        240            250           260     265
252   //    חלךmnoצ    מםpqrפרףst   uדאוvwxהסת    yzטזץ
253
254   float visualX05[] = { -100.f, 96.f, 155.f, 250.f, 344.f, 500.f,
255                         -100.f, 36.f, 124.f, 190.f, 280.f, 500.f,
256                         -100.f, 56.f, 158.f, 237.f, 303.f, 500.f,
257                         -100.f, 98.f, 184.f, 261.f, 337.f, 500.f,
258                         -100.f, 40.f, 113.f, 223.f, 302.f, 500.f,
259                         -100.f, 82.f, 160.f, 253.f, 500.f };
260   float visualY05[] = { -100.f, 12.f, 12.f, 12.f, 12.f, 12.f,
261                         30.f, 30.f, 30.f, 30.f, 30.f, 30.f,
262                         50.f, 50.f, 50.f, 50.f, 50.f, 50.f,
263                         67.f, 67.f, 67.f, 67.f, 67.f, 67.f,
264                         87.f, 87.f, 87.f, 87.f, 87.f, 87.f,
265                         107.f, 107.f, 107.f, 107.f, 107.f };
266   CharacterIndex logicalIndex05[] = {   0u,  10u,  20u,  30u,  40u,  45u,
267                                        46u,  50u,  60u,  70u,  80u,  92u,
268                                        93u, 100u, 110u, 120u, 130u, 138u,
269                                       139u, 150u, 160u, 170u, 180u, 185u,
270                                       186u, 190u, 200u, 210u, 220u, 232u,
271                                       233u, 240u, 250u, 260u, 265u };
272
273   //   0            10           20           30           40        46
274   //    שנבabcגקכd    efעיןghiחל   ךjklצמםmno   פרףpqrדאוs   tuהסתv
275   //  46     50           60          70            80              93
276   //    wxטז   ץyzשנבabcג   קכdefעיןgh   iחלךjklצמם   mnoפרףpqrדאוs
277   //  93        100          110          120           130           139
278   //    tuהסתvw   xטזץyzשנבa   bcגקכdefעי    ןghiחלךjkl    צמםmnoפרף
279   // 139           150           160          170         180       186
280   //    pqrדאוstuהס   תvwxטזץyzש   נבabcגקכde   fעיןghiחלך   jklצמם
281   // 186    190          200           210           220            232
282   //    mnoפ   רףpqrדאוst   uהסתvwxטזץ   yzשנבabcגק    כdefעיןghiחל
283   // 232         240           250           260     265
284   //    ךjklצמםm   noפרףpqrדא    וstuהסתvwx   טזץyz
285
286   float visualX06[] = { 500.f, 307.f, 237.f, 148.f, 55.f, -100.f,
287                         500.f, 362.f, 276.f, 213.f, 121.f, -100.f,
288                         500.f, 344.f, 238.f, 167.f, 93.f, -100.f,
289                         500.f, 306.f, 216.f, 142.f, 58.f, -100.f,
290                         500.f, 355.f, 279.f, 182.f, 92.f, -100.f,
291                         500.f, 326.f, 238.f, 150.f, -100.f };
292   float visualY06[] = { -100.f, 12.f, 12.f, 12.f, 12.f, 12.f,
293                         30.f, 30.f, 30.f, 30.f, 30.f, 30.f,
294                         50.f, 50.f, 50.f, 50.f, 50.f, 50.f,
295                         67.f, 67.f, 67.f, 67.f, 67.f, 67.f,
296                         87.f, 87.f, 87.f, 87.f, 87.f, 87.f,
297                         107.f, 107.f, 107.f, 107.f, 107.f };
298   CharacterIndex logicalIndex06[] = {   0u,  10u,  20u,  30u,  40u,  45u,
299                                        46u,  50u,  60u,  70u,  80u,  92u,
300                                        93u, 100u, 110u, 120u, 130u, 138u,
301                                       139u, 150u, 160u, 170u, 180u, 185u,
302                                       186u, 190u, 200u, 210u, 220u, 231u,
303                                       232u, 240u, 250u, 260u, 265u  };
304
305   struct GetClosestCursorIndexData data[] =
306   {
307     {
308       "Void text.",
309       "",
310       1u,
311       visualX01,
312       visualY01,
313       logicalIndex01
314     },
315     {
316       "Single line text.",
317       "Hello world שלום עולם",
318       7u,
319       visualX02,
320       visualY02,
321       logicalIndex02
322     },
323     {
324       "Single line with ligatures",
325       "different الأربعاء",
326       4u,
327       visualX03,
328       visualY03,
329       logicalIndex03
330     },
331     {
332       "Multiline. Single line paragraphs",
333       "Hello world\n"
334       "שלום עולם\n"
335       "different الأربعاء\n",
336       17u,
337       visualX04,
338       visualY04,
339       logicalIndex04
340     },
341     {
342       "Multiline. Single bidirectional paragraph, starts LTR, wrapped lines",
343       "abcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuדאוvwxה"
344       "סתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuד"
345       "אוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqr"
346       "פרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmno"
347       "צמםpqrפרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjkl"
348       "חלךmnoצמםpqrפרףstuדאוvwxהסתyzטזץ",
349       35u,
350       visualX05,
351       visualY05,
352       logicalIndex05
353     },
354     {
355       "Multiline. Single bidirectional paragraph, starts RTL, wrapped lines",
356       "שנבabcגקכdefעיןghiחלךjklצמםmnoפרףpqrדאוstuהסתv"
357       "wxטזץyzשנבabcגקכdefעיןghiחלךjklצמםmnoפרףpqrדאוs"
358       "tuהסתvwxטזץyzשנבabcגקכdefעיןghiחלךjklצמםmnoפרף"
359       "pqrדאוstuהסתvwxטזץyzשנבabcגקכdefעיןghiחלךjklצמם"
360       "mnoפרףpqrדאוstuהסתvwxטזץyzשנבabcגקכdefעיןghiחל"
361       "ךjklצמםmnoפרףpqrדאוstuהסתvwxטזץyz",
362       35u,
363       visualX06,
364       visualY06,
365       logicalIndex06
366     }
367   };
368   const unsigned int numberOfTests = 6u;
369
370   for( unsigned int index = 0u; index < numberOfTests; ++index )
371   {
372     ToolkitTestApplication application;
373     if( !GetClosestCursorIndexTest( data[index] ) )
374     {
375       tet_result(TET_FAIL);
376     }
377   }
378
379   tet_result(TET_PASS);
380   END_TEST;
381 }