[dali_2.1.7] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-VisualModel.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 <iostream>
19
20 #include <stdlib.h>
21
22 #include <dali-toolkit-test-suite-utils.h>
23 #include <dali-toolkit/dali-toolkit.h>
24 #include <toolkit-text-utils.h>
25
26 using namespace Dali;
27 using namespace Toolkit;
28 using namespace Text;
29
30 // Tests the following functions.
31 //
32 // void CreateCharacterToGlyphTable( CharacterIndex startIndex,
33 //                                   Length numberOfCharacters )
34 //
35 // void CreateGlyphsPerCharacterTable( CharacterIndex startIndex,
36 //                                     Length numberOfCharacters )
37
38 //////////////////////////////////////////////////////////
39
40 namespace
41 {
42 struct SetGlyphsPerCharacterData
43 {
44   std::string   description;             ///< Description of the test.
45   std::string   text;                    ///< Input text.
46   unsigned int  startIndex;              ///< The start index from where the glyphs per character table is set.
47   unsigned int  numberOfCharacters;      ///< The number of characters to set.
48   unsigned int  totalNumberOfCharacters; ///< The total number of characters.
49   unsigned int* glyphsPerCharacter;      ///< The number of glyphs per character.
50 };
51
52 struct SetCharacterToGlyphData
53 {
54   std::string   description;             ///< Description of the test.
55   std::string   text;                    ///< Input text.
56   unsigned int  startIndex;              ///< The start index from where the character to glyph table is set.
57   unsigned int  numberOfCharacters;      ///< The number of characters to set.
58   unsigned int  totalNumberOfCharacters; ///< The total number of characters.
59   unsigned int* glyphsIndices;           ///< The glyph indices.
60 };
61
62 bool SetGlyphsPerCharacterTest(const SetGlyphsPerCharacterData& data)
63 {
64   // 1) Create the model.
65   ModelPtr   textModel;
66   MetricsPtr metrics;
67   Size       textArea(100.f, 60.f);
68   Size       layoutSize;
69
70   const Vector<FontDescriptionRun> fontDescriptions;
71   const LayoutOptions              options;
72   CreateTextModel(data.text,
73                   textArea,
74                   fontDescriptions,
75                   options,
76                   layoutSize,
77                   textModel,
78                   metrics,
79                   false,
80                   LineWrap::WORD,
81                   false,
82                   Toolkit::DevelText::EllipsisPosition::END,
83                   0.0f, // lineSpacing
84                   0.0f  // characterSpacing
85   );
86
87   LogicalModelPtr logicalModel = textModel->mLogicalModel;
88   VisualModelPtr  visualModel  = textModel->mVisualModel;
89
90   Vector<GlyphIndex>& charactersToGlyph  = visualModel->mCharactersToGlyph;
91   Vector<Length>&     glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
92
93   // 2) Clear the model.
94
95   GlyphIndex startGlyphIndex = 0u;
96   if(0u != charactersToGlyph.Count())
97   {
98     // The number of glyphs to be removed.
99     const Length numberOfGlyphs = charactersToGlyph[data.startIndex + data.numberOfCharacters - 1u] + glyphsPerCharacter[data.startIndex + data.numberOfCharacters - 1u] - charactersToGlyph[data.startIndex];
100     startGlyphIndex             = charactersToGlyph[data.startIndex];
101
102     charactersToGlyph.Erase(charactersToGlyph.Begin() + data.startIndex,
103                             charactersToGlyph.Begin() + data.startIndex + data.numberOfCharacters);
104     glyphsPerCharacter.Erase(glyphsPerCharacter.Begin() + data.startIndex,
105                              glyphsPerCharacter.Begin() + data.startIndex + data.numberOfCharacters);
106
107     // Update the character to glyph indices.
108     for(Vector<GlyphIndex>::Iterator it    = charactersToGlyph.Begin() + data.startIndex,
109                                      endIt = charactersToGlyph.End();
110         it != endIt;
111         ++it)
112     {
113       *it -= numberOfGlyphs;
114     }
115   }
116
117   // 3) Call the CreateGlyphsPerCharacterTable() function
118   visualModel->CreateGlyphsPerCharacterTable(data.startIndex,
119                                              startGlyphIndex,
120                                              data.numberOfCharacters);
121
122   // 4) Compare the results.
123   if(data.totalNumberOfCharacters != glyphsPerCharacter.Count())
124   {
125     std::cout << "  Different number of characters : " << glyphsPerCharacter.Count() << ", expected : " << data.totalNumberOfCharacters << std::endl;
126     return false;
127   }
128
129   for(unsigned int i = 0u; i < data.totalNumberOfCharacters; ++i)
130   {
131     if(data.glyphsPerCharacter[i] != glyphsPerCharacter[i])
132     {
133       std::cout << "  Different number of glyphs for index " << i << std::endl;
134       for(unsigned int j = 0; j < data.totalNumberOfCharacters; ++j)
135       {
136         std::cout << glyphsPerCharacter[j] << " ";
137       }
138       std::cout << std::endl;
139       std::cout << "  expected" << std::endl;
140       for(unsigned int j = 0; j < data.totalNumberOfCharacters; ++j)
141       {
142         std::cout << data.glyphsPerCharacter[j] << " ";
143       }
144       std::cout << std::endl;
145       return false;
146     }
147   }
148
149   return true;
150 }
151
152 bool SetCharacterToGlyphTest(const SetCharacterToGlyphData& data)
153 {
154   // 1) Create the model.
155   ModelPtr   textModel;
156   MetricsPtr metrics;
157   Size       textArea(100.f, 60.f);
158   Size       layoutSize;
159
160   const Vector<FontDescriptionRun> fontDescriptions;
161   const LayoutOptions              options;
162   CreateTextModel(data.text,
163                   textArea,
164                   fontDescriptions,
165                   options,
166                   layoutSize,
167                   textModel,
168                   metrics,
169                   false,
170                   LineWrap::WORD,
171                   false,
172                   Toolkit::DevelText::EllipsisPosition::END,
173                   0.0f, // lineSpacing
174                   0.0f  // characterSpacing
175   );
176
177   LogicalModelPtr logicalModel = textModel->mLogicalModel;
178   VisualModelPtr  visualModel  = textModel->mVisualModel;
179
180   Vector<GlyphIndex>& charactersToGlyph  = visualModel->mCharactersToGlyph;
181   Vector<Length>&     glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
182
183   // 2) Clear the model.
184
185   GlyphIndex startGlyphIndex = 0u;
186   if(0u != charactersToGlyph.Count())
187   {
188     // The number of glyphs to be removed.
189     const Length numberOfGlyphs = charactersToGlyph[data.startIndex + data.numberOfCharacters - 1u] + glyphsPerCharacter[data.startIndex + data.numberOfCharacters - 1u] - charactersToGlyph[data.startIndex];
190     startGlyphIndex             = charactersToGlyph[data.startIndex];
191
192     charactersToGlyph.Erase(charactersToGlyph.Begin() + data.startIndex,
193                             charactersToGlyph.Begin() + data.startIndex + data.numberOfCharacters);
194
195     // Update the character to glyph indices.
196     for(Vector<GlyphIndex>::Iterator it    = charactersToGlyph.Begin() + data.startIndex,
197                                      endIt = charactersToGlyph.End();
198         it != endIt;
199         ++it)
200     {
201       *it -= numberOfGlyphs;
202     }
203   }
204
205   // 3) Call the CreateCharacterToGlyphTable() function
206   visualModel->CreateCharacterToGlyphTable(data.startIndex,
207                                            startGlyphIndex,
208                                            data.numberOfCharacters);
209
210   // 4) Compare the results.
211   if(data.totalNumberOfCharacters != charactersToGlyph.Count())
212   {
213     std::cout << "  Different number of character : " << charactersToGlyph.Count() << ", expected : " << data.totalNumberOfCharacters << std::endl;
214     return false;
215   }
216
217   for(unsigned int i = 0u; i < data.totalNumberOfCharacters; ++i)
218   {
219     if(data.glyphsIndices[i] != charactersToGlyph[i])
220     {
221       std::cout << "  Different number of character to glyph index " << i << std::endl;
222       for(unsigned int j = 0; j < data.totalNumberOfCharacters; ++j)
223       {
224         std::cout << charactersToGlyph[j] << " ";
225       }
226       std::cout << std::endl;
227       std::cout << "  expected" << std::endl;
228       for(unsigned int j = 0; j < data.totalNumberOfCharacters; ++j)
229       {
230         std::cout << data.glyphsIndices[j] << " ";
231       }
232       std::cout << std::endl;
233       return false;
234     }
235   }
236
237   return true;
238 }
239
240 } // namespace
241
242 //////////////////////////////////////////////////////////
243
244 int UtcDaliSetGlyphsPerCharacter(void)
245 {
246   tet_infoline(" UtcDaliSetGlyphsPerCharacter");
247
248   Length glyphsPerCharacter02[] = {1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u};
249   Length glyphsPerCharacter03[] = {1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u};
250   Length glyphsPerCharacter04[] = {1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 1u, 0u, 2u, 1u, 0u, 2u, 0u, 2u, 0u, 2u, 1u, 1u, 0u, 0u, 0u, 2u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 2u, 1u, 0u, 2u, 1u, 1u};
251
252   struct SetGlyphsPerCharacterData data[] =
253     {
254       {"Zero characters text",
255        "",
256        0u,
257        0u,
258        0u,
259        NULL},
260       {
261         "Simple 1 to 1 text",
262         "Hello world",
263         0u,
264         11u,
265         11u,
266         glyphsPerCharacter02,
267       },
268       {
269         "Text with different number of glyphs and characters.",
270         "Hello different world",
271         0u,
272         21u,
273         21u,
274         glyphsPerCharacter03,
275       },
276       {
277         "Text paragraphs with different number of glyphs and characters. Update initial paragraphs.",
278         "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
279         0u,
280         22u,
281         54u,
282         glyphsPerCharacter04,
283       },
284       {
285         "Text paragraphs with different number of glyphs and characters. Update mid paragraphs.",
286         "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
287         22u,
288         14u,
289         54u,
290         glyphsPerCharacter04,
291       },
292       {
293         "Text paragraphs with different number of glyphs and characters. Update final paragraphs.",
294         "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
295         36u,
296         18u,
297         54u,
298         glyphsPerCharacter04,
299       },
300     };
301   const unsigned int numberOfTests = 6u;
302
303   for(unsigned int index = 0u; index < numberOfTests; ++index)
304   {
305     ToolkitTestApplication application;
306     if(!SetGlyphsPerCharacterTest(data[index]))
307     {
308       tet_result(TET_FAIL);
309     }
310   }
311
312   tet_result(TET_PASS);
313   END_TEST;
314 }
315
316 int UtcDaliSetCharacterToGlyph(void)
317 {
318   tet_infoline(" UtcDaliSetGlyphsPerCharacter");
319
320   GlyphIndex glyphIndices02[] = {0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u};
321   GlyphIndex glyphIndices03[] = {0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u};
322   GlyphIndex glyphIndices04[] = {0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u, 21u, 22u, 23u, 23u, 24u, 24u, 26u, 27u, 27u, 29u, 29u, 31u, 31u, 33u, 34u, 35u, 35u, 35u, 35u, 37u, 38u, 39u, 40u, 41u, 42u, 42u, 42u, 44u, 45u, 45u, 47u, 48u};
323
324   struct SetCharacterToGlyphData data[] =
325     {
326       {"Zero characters text",
327        "",
328        0u,
329        0u,
330        0u,
331        NULL},
332       {
333         "Simple 1 to 1 text",
334         "Hello world",
335         0u,
336         11u,
337         11u,
338         glyphIndices02,
339       },
340       {
341         "Text with different number of glyphs and characters.",
342         "Hello different world",
343         0u,
344         21u,
345         21u,
346         glyphIndices03,
347       },
348       {
349         "Text paragraphs with different number of glyphs and characters. Update initial paragraphs.",
350         "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
351         0u,
352         22u,
353         54u,
354         glyphIndices04,
355       },
356       {
357         "Text paragraphs with different number of glyphs and characters. Update mid paragraphs.",
358         "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
359         22u,
360         14u,
361         54u,
362         glyphIndices04,
363       },
364       {
365         "Text paragraphs with different number of glyphs and characters. Update final paragraphs.",
366         "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
367         36u,
368         18u,
369         54u,
370         glyphIndices04,
371       },
372     };
373
374   const unsigned int numberOfTests = 6u;
375
376   for(unsigned int index = 0u; index < numberOfTests; ++index)
377   {
378     ToolkitTestApplication application;
379     if(!SetCharacterToGlyphTest(data[index]))
380     {
381       tet_result(TET_FAIL);
382     }
383   }
384
385   tet_result(TET_PASS);
386   END_TEST;
387 }