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