Support Ellipsis Position Property
[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                    false,
85                    Toolkit::DevelText::EllipsisPosition::END );
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
174   LogicalModelPtr logicalModel = textModel->mLogicalModel;
175   VisualModelPtr visualModel = textModel->mVisualModel;
176
177   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
178   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
179
180   // 2) Clear the model.
181
182   GlyphIndex startGlyphIndex = 0u;
183   if( 0u != charactersToGlyph.Count() )
184   {
185     // The number of glyphs to be removed.
186     const Length numberOfGlyphs = charactersToGlyph[data.startIndex + data.numberOfCharacters - 1u] + glyphsPerCharacter[data.startIndex + data.numberOfCharacters - 1u] - charactersToGlyph[data.startIndex];
187     startGlyphIndex = charactersToGlyph[data.startIndex];
188
189     charactersToGlyph.Erase( charactersToGlyph.Begin() + data.startIndex,
190                              charactersToGlyph.Begin() + data.startIndex + data.numberOfCharacters );
191
192     // Update the character to glyph indices.
193     for( Vector<GlyphIndex>::Iterator it = charactersToGlyph.Begin() + data.startIndex,
194            endIt = charactersToGlyph.End();
195          it != endIt;
196          ++it )
197     {
198       *it -= numberOfGlyphs;
199     }
200   }
201
202   // 3) Call the CreateCharacterToGlyphTable() function
203   visualModel->CreateCharacterToGlyphTable( data.startIndex,
204                                             startGlyphIndex,
205                                             data.numberOfCharacters );
206
207   // 4) Compare the results.
208   if( data.totalNumberOfCharacters != charactersToGlyph.Count() )
209   {
210     std::cout << "  Different number of character : " << charactersToGlyph.Count() << ", expected : " << data.totalNumberOfCharacters << std::endl;
211     return false;
212   }
213
214   for( unsigned int i = 0u; i < data.totalNumberOfCharacters; ++i )
215   {
216     if( data.glyphsIndices[i] != charactersToGlyph[i] )
217     {
218       std::cout << "  Different number of character to glyph index " << i << std::endl;
219       for( unsigned int j = 0; j < data.totalNumberOfCharacters; ++j )
220       {
221         std::cout << charactersToGlyph[j] << " ";
222       }
223       std::cout << std::endl;
224       std::cout << "  expected" << std::endl;
225       for( unsigned int j = 0; j < data.totalNumberOfCharacters; ++j )
226       {
227         std::cout << data.glyphsIndices[j] << " ";
228       }
229       std::cout << std::endl;
230       return false;
231     }
232   }
233
234   return true;
235 }
236
237 } // namespace
238
239 //////////////////////////////////////////////////////////
240
241 int UtcDaliSetGlyphsPerCharacter(void)
242 {
243   tet_infoline(" UtcDaliSetGlyphsPerCharacter");
244
245   Length glyphsPerCharacter02[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
246   Length glyphsPerCharacter03[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
247   Length glyphsPerCharacter04[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 1u,
248                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
249                                     1u, 1u, 1u, 1u, 0u, 1u, 0u, 2u, 1u, 0u,
250                                     2u, 0u, 2u, 0u, 2u, 1u, 1u, 0u, 0u, 0u,
251                                     2u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 2u, 1u,
252                                     0u, 2u, 1u, 1u };
253
254   struct SetGlyphsPerCharacterData data[] =
255   {
256     {
257       "Zero characters text",
258       "",
259       0u,
260       0u,
261       0u,
262       NULL
263     },
264     {
265       "Simple 1 to 1 text",
266       "Hello world",
267       0u,
268       11u,
269       11u,
270       glyphsPerCharacter02,
271     },
272     {
273       "Text with different number of glyphs and characters.",
274       "Hello different world",
275       0u,
276       21u,
277       21u,
278       glyphsPerCharacter03,
279     },
280     {
281       "Text paragraphs with different number of glyphs and characters. Update initial paragraphs.",
282       "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
283       0u,
284       22u,
285       54u,
286       glyphsPerCharacter04,
287     },
288     {
289       "Text paragraphs with different number of glyphs and characters. Update mid paragraphs.",
290       "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
291       22u,
292       14u,
293       54u,
294       glyphsPerCharacter04,
295     },
296     {
297       "Text paragraphs with different number of glyphs and characters. Update final paragraphs.",
298       "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
299       36u,
300       18u,
301       54u,
302       glyphsPerCharacter04,
303     },
304   };
305   const unsigned int numberOfTests = 6u;
306
307   for( unsigned int index = 0u; index < numberOfTests; ++index )
308   {
309     ToolkitTestApplication application;
310     if( !SetGlyphsPerCharacterTest( data[index] ) )
311     {
312       tet_result(TET_FAIL);
313     }
314   }
315
316   tet_result(TET_PASS);
317   END_TEST;
318 }
319
320 int UtcDaliSetCharacterToGlyph(void)
321 {
322   tet_infoline(" UtcDaliSetGlyphsPerCharacter");
323
324   GlyphIndex glyphIndices02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
325   GlyphIndex glyphIndices03[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u };
326   GlyphIndex glyphIndices04[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u,
327                                   21u, 22u, 23u, 23u, 24u, 24u, 26u, 27u, 27u, 29u, 29u, 31u, 31u, 33u,
328                                   34u, 35u, 35u, 35u, 35u, 37u, 38u, 39u, 40u, 41u, 42u, 42u, 42u, 44u, 45u, 45u, 47u, 48u };
329
330   struct SetCharacterToGlyphData data[] =
331   {
332     {
333       "Zero characters text",
334       "",
335       0u,
336       0u,
337       0u,
338       NULL
339     },
340     {
341       "Simple 1 to 1 text",
342       "Hello world",
343       0u,
344       11u,
345       11u,
346       glyphIndices02,
347     },
348     {
349       "Text with different number of glyphs and characters.",
350       "Hello different world",
351       0u,
352       21u,
353       21u,
354       glyphIndices03,
355     },
356     {
357       "Text paragraphs with different number of glyphs and characters. Update initial paragraphs.",
358       "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
359       0u,
360       22u,
361       54u,
362       glyphIndices04,
363     },
364     {
365       "Text paragraphs with different number of glyphs and characters. Update mid paragraphs.",
366       "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
367       22u,
368       14u,
369       54u,
370       glyphIndices04,
371     },
372     {
373       "Text paragraphs with different number of glyphs and characters. Update final paragraphs.",
374       "Hello different world\nनमस्ते दुनिया\nမင်္ဂလာပါကမ္ဘာလောက",
375       36u,
376       18u,
377       54u,
378       glyphIndices04,
379     },
380   };
381
382   const unsigned int numberOfTests = 6u;
383
384   for( unsigned int index = 0u; index < numberOfTests; ++index )
385   {
386     ToolkitTestApplication application;
387     if( !SetCharacterToGlyphTest( data[index] ) )
388     {
389       tet_result(TET_FAIL);
390     }
391   }
392
393   tet_result(TET_PASS);
394   END_TEST;
395 }