43157ff9d73a8859ec7a8b5cec867bc15bd2dba4
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-VisualModel.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <iostream>
19
20 #include <stdlib.h>
21
22 #include <dali-toolkit-test-suite-utils.h>
23 #include <dali-toolkit/dali-toolkit.h>
24 #include <toolkit-text-utils.h>
25
26
27 using namespace Dali;
28 using namespace Toolkit;
29 using namespace Text;
30
31 // Tests the following functions.
32 //
33 // void CreateCharacterToGlyphTable( CharacterIndex startIndex,
34 //                                   Length numberOfCharacters )
35 //
36 // void CreateGlyphsPerCharacterTable( CharacterIndex startIndex,
37 //                                     Length numberOfCharacters )
38
39
40 //////////////////////////////////////////////////////////
41
42 namespace
43 {
44
45 struct SetGlyphsPerCharacterData
46 {
47   std::string   description;             ///< Description of the test.
48   std::string   text;                    ///< Input text.
49   unsigned int  startIndex;              ///< The start index from where the glyphs per character table is set.
50   unsigned int  numberOfCharacters;      ///< The number of characters to set.
51   unsigned int  totalNumberOfCharacters; ///< The total number of characters.
52   unsigned int* glyphsPerCharacter;      ///< The number of glyphs per character.
53 };
54
55 struct SetCharacterToGlyphData
56 {
57   std::string   description;             ///< Description of the test.
58   std::string   text;                    ///< Input text.
59   unsigned int  startIndex;              ///< The start index from where the character to glyph table is set.
60   unsigned int  numberOfCharacters;      ///< The number of characters to set.
61   unsigned int  totalNumberOfCharacters; ///< The total number of characters.
62   unsigned int* glyphsIndices;           ///< The glyph indices.
63 };
64
65 bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data )
66 {
67   // 1) Create the model.
68   ModelPtr textModel;
69   MetricsPtr metrics;
70   Size textArea(100.f, 60.f);
71   Size layoutSize;
72
73   const Vector<FontDescriptionRun> fontDescriptions;
74   const LayoutOptions options;
75   CreateTextModel( data.text,
76                    textArea,
77                    fontDescriptions,
78                    options,
79                    layoutSize,
80                    textModel,
81                    metrics,
82                    false,
83                    LineWrap::WORD );
84
85   LogicalModelPtr logicalModel = textModel->mLogicalModel;
86   VisualModelPtr visualModel = textModel->mVisualModel;
87
88   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
89   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
90
91   // 2) Clear the model.
92
93   GlyphIndex startGlyphIndex = 0u;
94   if( 0u != charactersToGlyph.Count() )
95   {
96     // The number of glyphs to be removed.
97     const Length numberOfGlyphs = charactersToGlyph[data.startIndex + data.numberOfCharacters - 1u] + glyphsPerCharacter[data.startIndex + data.numberOfCharacters - 1u] - charactersToGlyph[data.startIndex];
98     startGlyphIndex = charactersToGlyph[data.startIndex];
99
100     charactersToGlyph.Erase( charactersToGlyph.Begin() + data.startIndex,
101                              charactersToGlyph.Begin() + data.startIndex + data.numberOfCharacters );
102     glyphsPerCharacter.Erase( glyphsPerCharacter.Begin() + data.startIndex,
103                               glyphsPerCharacter.Begin() + data.startIndex + data.numberOfCharacters );
104
105     // Update the character to glyph indices.
106     for( Vector<GlyphIndex>::Iterator it = charactersToGlyph.Begin() + data.startIndex,
107            endIt = charactersToGlyph.End();
108          it != endIt;
109          ++it )
110     {
111       *it -= numberOfGlyphs;
112     }
113   }
114
115   // 3) Call the CreateGlyphsPerCharacterTable() function
116   visualModel->CreateGlyphsPerCharacterTable( data.startIndex,
117                                               startGlyphIndex,
118                                               data.numberOfCharacters );
119
120   // 4) Compare the results.
121   if( data.totalNumberOfCharacters != glyphsPerCharacter.Count() )
122   {
123     std::cout << "  Different number of characters : " << glyphsPerCharacter.Count() << ", expected : " << data.totalNumberOfCharacters << std::endl;
124     return false;
125   }
126
127   for( unsigned int i = 0u; i < data.totalNumberOfCharacters; ++i )
128   {
129     if( data.glyphsPerCharacter[i] != glyphsPerCharacter[i] )
130     {
131       std::cout << "  Different number of glyphs for index " << i << std::endl;
132       for( unsigned int j = 0; j < data.totalNumberOfCharacters; ++j )
133       {
134         std::cout << glyphsPerCharacter[j] << " ";
135       }
136       std::cout << std::endl;
137       std::cout << "  expected" << std::endl;
138       for( unsigned int j = 0; j < data.totalNumberOfCharacters; ++j )
139       {
140         std::cout << data.glyphsPerCharacter[j] << " ";
141       }
142       std::cout << std::endl;
143       return false;
144     }
145   }
146
147   return true;
148 }
149
150 bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data )
151 {
152   // 1) Create the model.
153   ModelPtr textModel;
154   MetricsPtr metrics;
155   Size textArea(100.f, 60.f);
156   Size layoutSize;
157
158   const Vector<FontDescriptionRun> fontDescriptions;
159   const LayoutOptions options;
160   CreateTextModel( data.text,
161                    textArea,
162                    fontDescriptions,
163                    options,
164                    layoutSize,
165                    textModel,
166                    metrics,
167                    false,
168                    LineWrap::WORD );
169
170   LogicalModelPtr logicalModel = textModel->mLogicalModel;
171   VisualModelPtr visualModel = textModel->mVisualModel;
172
173   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
174   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
175
176   // 2) Clear the model.
177
178   GlyphIndex startGlyphIndex = 0u;
179   if( 0u != charactersToGlyph.Count() )
180   {
181     // The number of glyphs to be removed.
182     const Length numberOfGlyphs = charactersToGlyph[data.startIndex + data.numberOfCharacters - 1u] + glyphsPerCharacter[data.startIndex + data.numberOfCharacters - 1u] - charactersToGlyph[data.startIndex];
183     startGlyphIndex = charactersToGlyph[data.startIndex];
184
185     charactersToGlyph.Erase( charactersToGlyph.Begin() + data.startIndex,
186                              charactersToGlyph.Begin() + data.startIndex + data.numberOfCharacters );
187
188     // Update the character to glyph indices.
189     for( Vector<GlyphIndex>::Iterator it = charactersToGlyph.Begin() + data.startIndex,
190            endIt = charactersToGlyph.End();
191          it != endIt;
192          ++it )
193     {
194       *it -= numberOfGlyphs;
195     }
196   }
197
198   // 3) Call the CreateCharacterToGlyphTable() function
199   visualModel->CreateCharacterToGlyphTable( data.startIndex,
200                                             startGlyphIndex,
201                                             data.numberOfCharacters );
202
203   // 4) Compare the results.
204   if( data.totalNumberOfCharacters != charactersToGlyph.Count() )
205   {
206     std::cout << "  Different number of character : " << charactersToGlyph.Count() << ", expected : " << data.totalNumberOfCharacters << std::endl;
207     return false;
208   }
209
210   for( unsigned int i = 0u; i < data.totalNumberOfCharacters; ++i )
211   {
212     if( data.glyphsIndices[i] != charactersToGlyph[i] )
213     {
214       std::cout << "  Different number of character to glyph index " << i << std::endl;
215       for( unsigned int j = 0; j < data.totalNumberOfCharacters; ++j )
216       {
217         std::cout << charactersToGlyph[j] << " ";
218       }
219       std::cout << std::endl;
220       std::cout << "  expected" << std::endl;
221       for( unsigned int j = 0; j < data.totalNumberOfCharacters; ++j )
222       {
223         std::cout << data.glyphsIndices[j] << " ";
224       }
225       std::cout << std::endl;
226       return false;
227     }
228   }
229
230   return true;
231 }
232
233 } // namespace
234
235 //////////////////////////////////////////////////////////
236
237 int UtcDaliSetGlyphsPerCharacter(void)
238 {
239   tet_infoline(" UtcDaliSetGlyphsPerCharacter");
240
241   Length glyphsPerCharacter02[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
242   Length glyphsPerCharacter03[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
243   Length glyphsPerCharacter04[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 1u,
244                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
245                                     1u, 1u, 1u, 1u, 0u, 1u, 0u, 2u, 1u, 0u,
246                                     2u, 0u, 2u, 0u, 2u, 1u, 1u, 0u, 0u, 0u,
247                                     2u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 2u, 1u,
248                                     0u, 2u, 1u, 1u };
249
250   struct SetGlyphsPerCharacterData data[] =
251   {
252     {
253       "Zero characters text",
254       "",
255       0u,
256       0u,
257       0u,
258       NULL
259     },
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,
323                                   21u, 22u, 23u, 23u, 24u, 24u, 26u, 27u, 27u, 29u, 29u, 31u, 31u, 33u,
324                                   34u, 35u, 35u, 35u, 35u, 37u, 38u, 39u, 40u, 41u, 42u, 42u, 42u, 44u, 45u, 45u, 47u, 48u };
325
326   struct SetCharacterToGlyphData data[] =
327   {
328     {
329       "Zero characters text",
330       "",
331       0u,
332       0u,
333       0u,
334       NULL
335     },
336     {
337       "Simple 1 to 1 text",
338       "Hello world",
339       0u,
340       11u,
341       11u,
342       glyphIndices02,
343     },
344     {
345       "Text with different number of glyphs and characters.",
346       "Hello different world",
347       0u,
348       21u,
349       21u,
350       glyphIndices03,
351     },
352     {
353       "Text paragraphs with different number of glyphs and characters. Update initial paragraphs.",
354       "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
355       0u,
356       22u,
357       54u,
358       glyphIndices04,
359     },
360     {
361       "Text paragraphs with different number of glyphs and characters. Update mid paragraphs.",
362       "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
363       22u,
364       14u,
365       54u,
366       glyphIndices04,
367     },
368     {
369       "Text paragraphs with different number of glyphs and characters. Update final paragraphs.",
370       "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
371       36u,
372       18u,
373       54u,
374       glyphIndices04,
375     },
376   };
377
378   const unsigned int numberOfTests = 6u;
379
380   for( unsigned int index = 0u; index < numberOfTests; ++index )
381   {
382     ToolkitTestApplication application;
383     if( !SetCharacterToGlyphTest( data[index] ) )
384     {
385       tet_result(TET_FAIL);
386     }
387   }
388
389   tet_result(TET_PASS);
390   END_TEST;
391 }