Support Emoji sequences
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-Text-Shaping.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 #include <stdlib.h>
20 #include <unistd.h>
21
22 #include <dali-toolkit/internal/text/shaper.h>
23 #include <dali-toolkit-test-suite-utils.h>
24 #include <dali-toolkit/dali-toolkit.h>
25 #include <toolkit-text-utils.h>
26
27 using namespace Dali;
28 using namespace Toolkit;
29 using namespace Text;
30
31 // Tests the following function.
32 // void ShapeText( const Vector<Character>& text,
33 //                 const Vector<LineBreakInfo>& lineBreakInfo,
34 //                 const Vector<ScriptRun>& scripts,
35 //                 const Vector<FontRun>& fonts,
36 //                 CharacterIndex startCharacterIndex,
37 //                 GlyphIndex startGlyphIndex,
38 //                 Length numberOfCharacters,
39 //                 Vector<GlyphInfo>& glyphs,
40 //                 Vector<CharacterIndex>& glyphToCharacterMap,
41 //                 Vector<Length>& charactersPerGlyph,
42 //                 Vector<GlyphIndex>& newParagraphGlyphs );
43
44 //////////////////////////////////////////////////////////
45
46 namespace
47 {
48 const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
49
50 struct GlyphInfoData
51 {
52   FontId fontId;     ///< Identifies the font containing the glyph
53   GlyphIndex index;  ///< Uniquely identifies a glyph for a given FontId
54   float width;       ///< The width of the glyph
55   float height;      ///< The height of the glyph
56   float xBearing;    ///< The distance from the cursor position to the leftmost border of the glyph
57   float yBearing;    ///< The distance from the baseline to the topmost border of the glyph
58   float advance;     ///< The distance to move the cursor for this glyph
59   float scaleFactor; ///< The scaling applied (fixed-size fonts only)
60   bool isItalicRequired; ///< Whether the italic style is required.
61   bool isBoldRequired;   ///< Whether the bold style is required.
62 };
63
64 bool IsEqualGlyph ( const GlyphInfoData& glyphData, const GlyphInfo& glyph )
65 {
66   if( glyphData.fontId != glyph.fontId )
67   {
68     return false;
69   }
70   if( glyphData.index != glyph.index )
71   {
72     return false;
73   }
74   if( fabsf( glyphData.width - glyph.width ) > Math::MACHINE_EPSILON_1000 )
75   {
76     return false;
77   }
78   if( fabsf( glyphData.height - glyph.height ) > Math::MACHINE_EPSILON_1000 )
79   {
80     return false;
81   }
82   if( fabsf( glyphData.xBearing - glyph.xBearing ) > Math::MACHINE_EPSILON_1000 )
83   {
84     return false;
85   }
86   if( fabsf( glyphData.yBearing - glyph.yBearing ) > Math::MACHINE_EPSILON_1000 )
87   {
88     return false;
89   }
90   if( fabsf( glyphData.advance - floor(glyph.advance) ) > Math::MACHINE_EPSILON_1000 )
91   {
92     return false;
93   }
94   if( fabsf( glyphData.scaleFactor - glyph.scaleFactor ) > Math::MACHINE_EPSILON_1000 )
95   {
96     return false;
97   }
98   if( glyphData.isItalicRequired != glyph.isItalicRequired )
99   {
100     return false;
101   }
102   if( glyphData.isBoldRequired != glyph.isBoldRequired )
103   {
104     return false;
105   }
106
107   return true;
108 }
109
110 struct ShapeInfoData
111 {
112   std::string     description;                        ///< Description of the test.
113   std::string     text;                               ///< input text.
114   uint32_t        index;                              ///< The index from where to start to query the break info.
115   uint32_t        numberOfCharacters;                 ///< The requested number of characters.
116   uint32_t        expectedNumberOfGlyphs;             ///< The expected number of glyphs.
117   GlyphInfoData*  glyphs;                             ///< The glyphs.
118   CharacterIndex* characterIndices;                   ///< The character index for each glyph.
119   Length*         charactersPerGlyph;                 ///< The characters per glyph.
120   uint32_t        expectedNumberOfNewParagraphGlyphs; ///< The expected number of glyphs.
121   GlyphIndex*     newParagraphGlyphs;                 ///< Indices to the new paragraphs glyphs.
122   bool            markupProcessorEnabled;             //< Enable markup processor to use markup text.
123   Vector<FontDescriptionRun> fontDescriptions;        ///< Fonts which is used for text.
124 };
125
126 bool ShapeInfoTest( const ShapeInfoData& data )
127 {
128   // 1) Create the model.
129   ModelPtr textModel;
130   MetricsPtr metrics;
131   Size textArea(100.f, 60.f);
132   Size layoutSize;
133
134   const Vector<FontDescriptionRun> fontDescriptions;
135   const LayoutOptions options;
136
137   CreateTextModel( data.text,
138                    textArea,
139                    data.fontDescriptions,
140                    options,
141                    layoutSize,
142                    textModel,
143                    metrics,
144                    data.markupProcessorEnabled,
145                    LineWrap::WORD,
146                    false,
147                    Toolkit::DevelText::EllipsisPosition::END );
148
149   LogicalModelPtr logicalModel = textModel->mLogicalModel;
150   VisualModelPtr visualModel = textModel->mVisualModel;
151
152   // 2) Clear the model.
153
154   Vector<GlyphInfo>& glyphs = visualModel->mGlyphs;
155   Vector<CharacterIndex>& glyphToCharacter = visualModel->mGlyphsToCharacters;
156   Vector<Length>& charactersPerGlyph = visualModel->mCharactersPerGlyph;
157   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
158   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
159
160   // Get the glyph index.
161   GlyphIndex glyphIndex = 0u;
162   if( 0u != visualModel->mCharactersToGlyph.Count() )
163   {
164     glyphIndex = *( visualModel->mCharactersToGlyph.Begin() + data.index );
165
166     const CharacterIndex lastCharacterIndex = data.index + data.numberOfCharacters - 1u;
167     const Length numberOfGlyphs = *( visualModel->mCharactersToGlyph.Begin() + lastCharacterIndex ) + *( visualModel->mGlyphsPerCharacter.Begin() + lastCharacterIndex ) - glyphIndex;
168
169     // Erase the glyph info from the text model.
170     // Got from the ShapeText() function.
171     glyphs.Erase( glyphs.Begin() + glyphIndex, glyphs.Begin() + glyphIndex + numberOfGlyphs );
172     glyphToCharacter.Erase( glyphToCharacter.Begin() + glyphIndex, glyphToCharacter.Begin() + glyphIndex + numberOfGlyphs );
173     charactersPerGlyph.Erase( charactersPerGlyph.Begin() + glyphIndex, charactersPerGlyph.Begin() + glyphIndex + numberOfGlyphs );
174
175     // Got from the VisualModel::CreateCharacterToGlyphTable() and the VisualModel::CreateGlyphsPerCharacterTable() methods.
176     charactersToGlyph.Erase( charactersToGlyph.Begin() + data.index,
177                              charactersToGlyph.Begin() + data.index + data.numberOfCharacters );
178     glyphsPerCharacter.Erase( glyphsPerCharacter.Begin() + data.index,
179                               glyphsPerCharacter.Begin() + data.index + data.numberOfCharacters );
180
181     // Update the glyph to character indices.
182     for( Vector<CharacterIndex>::Iterator it = glyphToCharacter.Begin() + glyphIndex,
183            endIt = glyphToCharacter.End();
184          it != endIt;
185          ++it )
186     {
187       CharacterIndex& index = *it;
188       index -= data.numberOfCharacters;
189     }
190
191   }
192
193   // Reset the metrics got from the model as the ShapeText() function doesn't retrieve them.
194   for( Vector<GlyphInfo>::Iterator it = glyphs.Begin(),
195          endIt = glyphs.End();
196        it != endIt;
197        ++it )
198   {
199     GlyphInfo& info = *it;
200     info.width = 0.f;
201     info.height = 0.f;
202     info.xBearing = 0.f;
203     info.yBearing = 0.f;
204     info.scaleFactor = 0.f;
205   }
206
207   // 3) Call the ShapeText() function.
208
209   Vector<GlyphIndex> newParagraphGlyphs;
210
211   ShapeText( logicalModel->mText,
212              logicalModel->mLineBreakInfo,
213              logicalModel->mScriptRuns,
214              logicalModel->mFontRuns,
215              data.index,
216              glyphIndex,
217              data.numberOfCharacters,
218              glyphs,
219              glyphToCharacter,
220              charactersPerGlyph,
221              newParagraphGlyphs );
222
223   // Clear the advance of the new paragraph glyphs.
224   for( Vector<GlyphIndex>::Iterator it = newParagraphGlyphs.Begin(),
225          endIt = newParagraphGlyphs.End();
226        it != endIt;
227        ++it )
228   {
229     GlyphInfo& info = *( glyphs.Begin() + *it );
230     info.advance = 0.f;
231   }
232
233   // 4) Compare the results.
234
235   if( data.expectedNumberOfGlyphs != glyphs.Count() )
236   {
237     std::cout << "  Different number of glyphs : " << glyphs.Count() << ", expected : " << data.expectedNumberOfGlyphs << std::endl;
238     return false;
239   }
240
241   for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
242   {
243     if( !IsEqualGlyph( data.glyphs[index], glyphs[index] ) )
244     {
245       std::cout << "  different glyph info, index : " << index << std::endl;
246
247       const GlyphInfo& glyphInfo = glyphs[index];
248       std::cout << "            fontId : " << glyphInfo.fontId << std::endl;
249       std::cout << "             index : " << glyphInfo.index << std::endl;
250       std::cout << "             width : " << glyphInfo.width << std::endl;
251       std::cout << "            height : " << glyphInfo.height << std::endl;
252       std::cout << "          xBearing : " << glyphInfo.xBearing << std::endl;
253       std::cout << "          yBearing : " << glyphInfo.yBearing << std::endl;
254       std::cout << "           advance : " << floor(glyphInfo.advance) << std::endl;
255       std::cout << "       scaleFactor : " << glyphInfo.scaleFactor << std::endl;
256       std::cout << "  isItalicRequired : " << glyphInfo.isItalicRequired << std::endl;
257       std::cout << "    isBoldRequired : " << glyphInfo.isBoldRequired << std::endl;
258
259       std::cout << "  Expected : " << std::endl;
260       const GlyphInfoData& expectedGlyphInfo = data.glyphs[index];
261       std::cout << "            fontId : " << expectedGlyphInfo.fontId << std::endl;
262       std::cout << "             index : " << expectedGlyphInfo.index << std::endl;
263       std::cout << "             width : " << expectedGlyphInfo.width << std::endl;
264       std::cout << "            height : " << expectedGlyphInfo.height << std::endl;
265       std::cout << "          xBearing : " << expectedGlyphInfo.xBearing << std::endl;
266       std::cout << "          yBearing : " << expectedGlyphInfo.yBearing << std::endl;
267       std::cout << "           advance : " << expectedGlyphInfo.advance << std::endl;
268       std::cout << "       scaleFactor : " << expectedGlyphInfo.scaleFactor << std::endl;
269       std::cout << "  isItalicRequired : " << expectedGlyphInfo.isItalicRequired << std::endl;
270       std::cout << "    isBoldRequired : " << expectedGlyphInfo.isBoldRequired << std::endl;
271
272
273       return false;
274     }
275   }
276
277   for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
278   {
279     if( data.characterIndices[index] != glyphToCharacter[index] )
280     {
281       std::cout << "  different character index, index : " << index << std::endl;
282       return false;
283     }
284   }
285
286   for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
287   {
288     if( data.charactersPerGlyph[index] != charactersPerGlyph[index] )
289     {
290       std::cout << "  different character per glyph, index : " << index << std::endl;
291       return false;
292     }
293   }
294
295   if( data.expectedNumberOfNewParagraphGlyphs != newParagraphGlyphs.Count() )
296   {
297     std::cout << "  Different number of new paragraph glyphs : " << newParagraphGlyphs.Count() << ", expected : " << data.expectedNumberOfNewParagraphGlyphs << std::endl;
298     return false;
299   }
300
301   for( unsigned int index = 0u; index < data.expectedNumberOfNewParagraphGlyphs; ++index )
302   {
303     if( data.newParagraphGlyphs[index] != newParagraphGlyphs[index] )
304     {
305       std::cout << "  different new paragraph glyph, index : " << index << std::endl;
306       return false;
307     }
308   }
309
310   return true;
311 }
312
313 void LoadTextShapeFonts()
314 {
315   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
316   fontClient.SetDpi( 96u, 96u );
317
318   char* pathNamePtr = get_current_dir_name();
319   const std::string pathName( pathNamePtr );
320   free( pathNamePtr );
321
322   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" );
323   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/noto/NotoSansMalayalam-Regular.ttf" );
324 }
325
326 void LoadSoftwareStylingFonts()
327 {
328   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
329   fontClient.SetDpi( 96u, 96u );
330
331   char* pathNamePtr = get_current_dir_name();
332   const std::string pathName( pathNamePtr );
333   free( pathNamePtr );
334
335   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/roboto/Roboto-Regular.ttf" );
336   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/roboto/Roboto-Bold.ttf" );
337   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/roboto/Roboto-Italic.ttf" );
338   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/roboto/Roboto-BoldItalic.ttf" );
339 }
340
341 void LoadEmojiFonts()
342 {
343   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
344   fontClient.ClearCache();
345   fontClient.SetDpi( 96u, 96u );
346
347   char* pathNamePtr = get_current_dir_name();
348   const std::string pathName( pathNamePtr );
349   free( pathNamePtr );
350
351
352   TextAbstraction::FontDescription fontDescriptionText;
353   fontDescriptionText.path   = "";
354   fontDescriptionText.family = "DejaVuSans";
355   fontDescriptionText.width  = TextAbstraction::FontWidth::NONE;
356   fontDescriptionText.weight = TextAbstraction::FontWeight::NORMAL;
357   fontDescriptionText.slant  = TextAbstraction::FontSlant::NONE;
358   fontClient.GetFontId(fontDescriptionText, TextAbstraction::FontClient::DEFAULT_POINT_SIZE);
359
360   TextAbstraction::FontDescription fontDescriptionEmoji;
361   fontDescriptionEmoji.path   = "";
362   fontDescriptionEmoji.family = "NotoColorEmoji";
363   fontDescriptionEmoji.width  = TextAbstraction::FontWidth::NONE;
364   fontDescriptionEmoji.weight = TextAbstraction::FontWeight::NORMAL;
365   fontDescriptionEmoji.slant  = TextAbstraction::FontSlant::NONE;
366   fontClient.GetFontId(fontDescriptionEmoji, TextAbstraction::FontClient::DEFAULT_POINT_SIZE);
367 }
368
369 } // namespace
370
371 //////////////////////////////////////////////////////////
372
373 int UtcDaliTextShape(void)
374 {
375   tet_infoline(" UtcDaliTextShape");
376
377   struct GlyphInfoData glyphs02[] =
378   {
379     { 1u, 276u, 0.f, 0.f, 0.f, 0.f, 11.f, 0.f },
380     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
381     { 1u, 306u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
382     { 1u, 306u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
383     { 1u, 309u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
384     { 1u,   3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
385     { 1u, 317u, 0.f, 0.f, 0.f, 0.f, 11.f, 0.f },
386     { 1u, 309u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
387     { 1u, 312u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
388     { 1u, 306u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
389     { 1u, 298u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
390   };
391
392   CharacterIndex characterIndices02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
393   Length charactersPerGlyph02[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
394
395   struct GlyphInfoData glyphs03[] =
396   {
397     { 1u, 276u, 0.f, 0.f, 0.f, 0.f, 11.f, 0.f },
398     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
399     { 1u, 306u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
400     { 1u, 306u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
401     { 1u, 309u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
402     { 1u,   3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
403     { 1u, 317u, 0.f, 0.f, 0.f, 0.f, 11.f, 0.f },
404     { 1u, 309u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
405     { 1u, 312u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
406     { 1u, 306u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
407     { 1u, 298u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
408     { 1u,   0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
409     { 1u, 298u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
410     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
411     { 1u, 307u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
412     { 1u, 309u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
413     { 1u,   0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
414   };
415
416   CharacterIndex characterIndices03[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u };
417   Length charactersPerGlyph03[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
418   CharacterIndex newParagraphGlyphs03[] = { 11u, 16u };
419
420   struct GlyphInfoData glyphs04[] =
421   {
422     { 2u, 67u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
423     { 2u, 27u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
424     { 2u, 59u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
425     { 2u, 67u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
426     { 2u, 55u, 0.f, 0.f, 0.f, 0.f, 19.f, 0.f },
427     { 2u, 59u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
428     { 2u, 67u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
429     { 2u, 56u, 0.f, 0.f, 0.f, 0.f, 19.f, 0.f },
430     { 2u, 59u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
431     { 2u, 67u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
432     { 2u, 52u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
433     { 2u, 59u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
434   };
435
436   CharacterIndex characterIndices04[] = { 0u, 0u, 0u, 2u, 2u, 2u, 4u, 4u, 4u, 6u, 6u, 6u };
437   Length charactersPerGlyph04[] = { 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u };
438
439   struct GlyphInfoData glyphs05[] =
440   {
441     { 1u, 280u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
442     { 1u, 309u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
443     { 1u, 312u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
444     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
445     { 1u, 307u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
446     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
447     { 1u, 303u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
448     { 1u, 310u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
449     { 1u, 313u, 0.f, 0.f, 0.f, 0.f,  7.f, 0.f },
450     { 1u, 315u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
451     { 1u, 307u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
452     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
453     { 1u, 298u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
454     { 1u, 309u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
455     { 1u, 306u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
456     { 1u, 309u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
457     { 1u, 312u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
458     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
459     { 1u, 313u, 0.f, 0.f, 0.f, 0.f,  7.f, 0.f },
460     { 1u, 303u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
461     { 1u, 314u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
462     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
463     { 1u, 295u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
464     { 1u, 307u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
465     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
466     { 1u, 314u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
467     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
468     { 1u, 295u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
469     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
470     { 1u, 311u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
471     { 1u, 315u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
472     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
473     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
474     { 1u, 298u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
475     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
476     { 1u, 403u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
477     { 1u, 308u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
478     { 1u, 303u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
479     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
480     { 1u, 296u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
481     { 1u, 295u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
482     { 1u, 313u, 0.f, 0.f, 0.f, 0.f,  7.f, 0.f },
483     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
484     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
485     { 1u, 295u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
486     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
487     { 1u, 307u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
488     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
489     { 1u, 303u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
490     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
491     { 1u, 310u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
492     { 1u, 309u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
493     { 1u, 313u, 0.f, 0.f, 0.f, 0.f,  7.f, 0.f },
494     { 1u, 313u, 0.f, 0.f, 0.f, 0.f,  7.f, 0.f },
495     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
496     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
497     { 1u, 303u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
498     { 1u, 312u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
499     { 1u, 295u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
500     { 1u, 297u, 0.f, 0.f, 0.f, 0.f,  7.f, 0.f },
501     { 1u, 315u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
502     { 1u, 308u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
503     { 1u, 298u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
504     { 1u, 303u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
505     { 1u, 295u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
506     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
507     { 1u, 308u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
508     { 1u, 299u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
509     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
510     { 1u, 297u, 0.f, 0.f, 0.f, 0.f,  7.f, 0.f },
511     { 1u, 315u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
512     { 1u, 307u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
513     { 1u,  4u, 0.f, 0.f, 0.f, 0.f,  3.f, 0.f },
514     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
515   };
516
517   CharacterIndex characterIndices05[] = {  0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u,
518                                           10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u,
519                                           20u, 21u, 22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u,
520                                           30u, 31u, 32u, 33u, 34u, 35u, 37u, 38u, 39u, 40u,
521                                           41u, 42u, 43u, 44u, 45u, 46u, 47u, 48u, 49u, 50u,
522                                           51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u,
523                                           61u, 62u, 63u, 64u, 65u, 66u, 67u, 68u, 69u, 70u,
524                                           71u, 72u, 73u, 74u };
525   Length charactersPerGlyph05[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
526                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
527                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
528                                     1u, 1u, 1u, 1u, 1u, 2u, 1u, 1u, 1u, 1u,
529                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
530                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
531                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
532                                     1u, 1u, 1u, 1u };
533   CharacterIndex newParagraphGlyphs05[] = { 26u };
534   CharacterIndex newParagraphGlyphs06[] = { 49u };
535   CharacterIndex newParagraphGlyphs07[] = { 73u };
536
537   Vector<FontDescriptionRun> fontDescriptions01;
538   Vector<FontDescriptionRun> fontDescriptions02;
539   Vector<FontDescriptionRun> fontDescriptions03;
540   Vector<FontDescriptionRun> fontDescriptions04;
541   Vector<FontDescriptionRun> fontDescriptions05;
542   Vector<FontDescriptionRun> fontDescriptions06;
543
544   const std::string fontFamily( "TizenSans" );
545   const std::string fontFamilyMalayalam( "Noto Sans Malayalam" );
546
547   FontDescriptionRun fontDescriptionRun01 =
548   {
549     {
550       0u,
551       11u
552     },
553     nullptr,
554     0u,
555     TextAbstraction::FontWeight::NONE,
556     TextAbstraction::FontWidth::NONE,
557     TextAbstraction::FontSlant::NONE,
558     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
559     true,
560     false,
561     false,
562     false,
563     false
564   };
565   fontDescriptionRun01.familyLength = fontFamily.size();
566   fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
567   memcpy( fontDescriptionRun01.familyName, fontFamily.c_str(), fontDescriptionRun01.familyLength );
568
569   fontDescriptions01.PushBack( fontDescriptionRun01 );
570
571   FontDescriptionRun fontDescriptionRun02 =
572   {
573     {
574       0u,
575       17u
576     },
577     nullptr,
578     0u,
579     TextAbstraction::FontWeight::NONE,
580     TextAbstraction::FontWidth::NONE,
581     TextAbstraction::FontSlant::NONE,
582     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
583     true,
584     false,
585     false,
586     false,
587     false
588   };
589   fontDescriptionRun02.familyLength = fontFamily.size();
590   fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
591   memcpy( fontDescriptionRun02.familyName, fontFamily.c_str(), fontDescriptionRun02.familyLength );
592
593   fontDescriptions02.PushBack( fontDescriptionRun02 );
594
595   FontDescriptionRun fontDescriptionRun03 =
596   {
597     {
598       0u,
599       8u
600     },
601     nullptr,
602     0u,
603     TextAbstraction::FontWeight::NONE,
604     TextAbstraction::FontWidth::NONE,
605     TextAbstraction::FontSlant::NONE,
606     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
607     true,
608     false,
609     false,
610     false,
611     false
612   };
613   fontDescriptionRun03.familyLength = fontFamilyMalayalam.size();
614   fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
615   memcpy( fontDescriptionRun03.familyName, fontFamilyMalayalam.c_str(), fontDescriptionRun03.familyLength );
616
617   fontDescriptions03.PushBack( fontDescriptionRun03 );
618
619   FontDescriptionRun fontDescriptionRun04 =
620   {
621     {
622       0u,
623       75u
624     },
625     nullptr,
626     0u,
627     TextAbstraction::FontWeight::NONE,
628     TextAbstraction::FontWidth::NONE,
629     TextAbstraction::FontSlant::NONE,
630     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
631     true,
632     false,
633     false,
634     false,
635     false
636   };
637   fontDescriptionRun04.familyLength = fontFamily.size();
638   fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
639   memcpy( fontDescriptionRun04.familyName, fontFamily.c_str(), fontDescriptionRun04.familyLength );
640
641   fontDescriptions04.PushBack( fontDescriptionRun04 );
642
643   FontDescriptionRun fontDescriptionRun05 =
644   {
645     {
646       0u,
647       75u
648     },
649     nullptr,
650     0u,
651     TextAbstraction::FontWeight::NONE,
652     TextAbstraction::FontWidth::NONE,
653     TextAbstraction::FontSlant::NONE,
654     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
655     true,
656     false,
657     false,
658     false,
659     false
660   };
661   fontDescriptionRun05.familyLength = fontFamily.size();
662   fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
663   memcpy( fontDescriptionRun05.familyName, fontFamily.c_str(), fontDescriptionRun05.familyLength );
664
665   fontDescriptions05.PushBack( fontDescriptionRun05 );
666
667   FontDescriptionRun fontDescriptionRun06 =
668   {
669     {
670       0u,
671       75u
672     },
673     nullptr,
674     0u,
675     TextAbstraction::FontWeight::NONE,
676     TextAbstraction::FontWidth::NONE,
677     TextAbstraction::FontSlant::NONE,
678     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
679     true,
680     false,
681     false,
682     false,
683     false
684   };
685   fontDescriptionRun06.familyLength = fontFamily.size();
686   fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
687   memcpy( fontDescriptionRun06.familyName, fontFamily.c_str(), fontDescriptionRun06.familyLength );
688
689   fontDescriptions06.PushBack( fontDescriptionRun06 );
690
691   struct ShapeInfoData data[] =
692   {
693     {
694       "Zero characters",
695       "",
696       0u,
697       0u,
698       0u,
699       nullptr,
700       nullptr,
701       nullptr,
702       0u,
703       nullptr,
704       false,
705     },
706     {
707       "Latin script",
708       "Hello world",
709       0u,
710       11u,
711       11u,
712       glyphs02,
713       characterIndices02,
714       charactersPerGlyph02,
715       0u,
716       nullptr,
717       false,
718       fontDescriptions01
719     },
720     {
721       "Latin script. Some paragraphs.",
722       "Hello world\ndemo\n",
723       0u,
724       17u,
725       17u,
726       glyphs03,
727       characterIndices03,
728       charactersPerGlyph03,
729       2u,
730       newParagraphGlyphs03,
731       false,
732       fontDescriptions02
733     },
734     {
735       "Malayalam script. More glyphs than characters.",
736       "ജോസോഹോവോ",
737       0u,
738       8u,
739       12u,
740       glyphs04,
741       characterIndices04,
742       charactersPerGlyph04,
743       0u,
744       nullptr,
745       false,
746       fontDescriptions03
747     },
748     {
749       "Latin script with some paragraphs. Update initial paragraph.",
750       "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
751       0u,
752       27u,
753       74u,
754       glyphs05,
755       characterIndices05,
756       charactersPerGlyph05,
757       1u,
758       newParagraphGlyphs05,
759       false,
760       fontDescriptions04,
761     },
762     {
763       "Latin script with some paragraphs. Update mid paragraph.",
764       "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
765       27u,
766       24u,
767       74u,
768       glyphs05,
769       characterIndices05,
770       charactersPerGlyph05,
771       1u,
772       newParagraphGlyphs06,
773       false,
774       fontDescriptions05
775     },
776     {
777       "Latin script with some paragraphs. Update final paragraph.",
778       "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
779       51u,
780       24u,
781       74u,
782       glyphs05,
783       characterIndices05,
784       charactersPerGlyph05,
785       1u,
786       newParagraphGlyphs07,
787       false,
788       fontDescriptions06
789     },
790   };
791   const unsigned int numberOfTests = 7u;
792
793   for( unsigned int index = 0u; index < numberOfTests; ++index )
794   {
795     ToolkitTestApplication application;
796     LoadTextShapeFonts();
797
798     if( !ShapeInfoTest( data[index] ) )
799     {
800       tet_result(TET_FAIL);
801     }
802   }
803
804   tet_result(TET_PASS);
805   END_TEST;
806 }
807
808 int UtcDaliTextSoftwareStyling(void)
809 {
810   tet_infoline(" UtcDaliTextSoftwareStyling");
811
812   struct GlyphInfoData glyphs01[] =
813   {
814     { 4u, 38u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, true, true },
815     { 4u, 39u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f, true, true },
816     { 4u, 40u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, true, true },
817     { 4u, 41u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, true, true },
818   };
819   struct GlyphInfoData glyphs02[] =
820   {
821     { 1u, 38u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, false, false },
822     { 2u, 39u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, false,  true },
823     { 3u, 40u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, true,  false },
824     { 4u, 41u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, true,   true },
825   };
826
827   CharacterIndex characterIndices[] = { 0u, 1u, 2u, 3u };
828   Length charactersPerGlyph[] = { 1u, 1u, 1u, 1u };
829
830   Vector<FontDescriptionRun> fontDescriptions01;
831   Vector<FontDescriptionRun> fontDescriptions02;
832
833   const std::string fontFamily( "Roboto" );
834
835   FontDescriptionRun fontDescriptionRun01 =
836   {
837     {
838       0u,
839       4u
840     },
841     nullptr,
842     0u,
843     TextAbstraction::FontWeight::BOLD,
844     TextAbstraction::FontWidth::NONE,
845     TextAbstraction::FontSlant::ITALIC,
846     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
847     true,
848     true,
849     false,
850     true,
851     false
852   };
853   fontDescriptionRun01.familyLength = fontFamily.size();
854   fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
855   memcpy( fontDescriptionRun01.familyName, fontFamily.c_str(), fontDescriptionRun01.familyLength );
856
857   fontDescriptions01.PushBack(fontDescriptionRun01);
858
859   FontDescriptionRun fontDescriptionRun02 =
860   {
861     {
862       0u,
863       1u
864     },
865     nullptr,
866     0u,
867     TextAbstraction::FontWeight::NONE,
868     TextAbstraction::FontWidth::NONE,
869     TextAbstraction::FontSlant::NONE,
870     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
871     true,
872     false,
873     false,
874     false,
875     false
876   };
877   fontDescriptionRun02.familyLength = fontFamily.size();
878   fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
879   memcpy( fontDescriptionRun02.familyName, fontFamily.c_str(), fontDescriptionRun02.familyLength );
880
881   FontDescriptionRun fontDescriptionRun03 =
882   {
883     {
884       1u,
885       1u
886     },
887     nullptr,
888     0u,
889     TextAbstraction::FontWeight::BOLD,
890     TextAbstraction::FontWidth::NONE,
891     TextAbstraction::FontSlant::NONE,
892     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
893     true,
894     true,
895     false,
896     false,
897     false
898   };
899   fontDescriptionRun03.familyLength = fontFamily.size();
900   fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
901   memcpy( fontDescriptionRun03.familyName, fontFamily.c_str(), fontDescriptionRun03.familyLength );
902
903   FontDescriptionRun fontDescriptionRun04 =
904   {
905     {
906       2u,
907       1u
908     },
909     nullptr,
910     0u,
911     TextAbstraction::FontWeight::NONE,
912     TextAbstraction::FontWidth::NONE,
913     TextAbstraction::FontSlant::ITALIC,
914     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
915     true,
916     false,
917     false,
918     true,
919     false
920   };
921   fontDescriptionRun04.familyLength = fontFamily.size();
922   fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
923   memcpy( fontDescriptionRun04.familyName, fontFamily.c_str(), fontDescriptionRun04.familyLength );
924
925   FontDescriptionRun fontDescriptionRun05 =
926   {
927     {
928       3u,
929       1u
930     },
931     nullptr,
932     0u,
933     TextAbstraction::FontWeight::BOLD,
934     TextAbstraction::FontWidth::NONE,
935     TextAbstraction::FontSlant::ITALIC,
936     TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
937     true,
938     true,
939     false,
940     true,
941     false
942   };
943   fontDescriptionRun05.familyLength = fontFamily.size();
944   fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
945   memcpy( fontDescriptionRun05.familyName, fontFamily.c_str(), fontDescriptionRun05.familyLength );
946
947   fontDescriptions02.PushBack(fontDescriptionRun02);
948   fontDescriptions02.PushBack(fontDescriptionRun03);
949   fontDescriptions02.PushBack(fontDescriptionRun04);
950   fontDescriptions02.PushBack(fontDescriptionRun05);
951
952
953   struct ShapeInfoData data[] =
954   {
955     {
956       "Latin script. Characters have same font description",
957       "ABCD",
958       0u,
959       4u,
960       4u,
961       glyphs01,
962       characterIndices,
963       charactersPerGlyph,
964       0u,
965       nullptr,
966       false,
967       fontDescriptions01
968     },
969     {
970       "Latin script. Each character has different font description.",
971       "ABCD",
972       0u,
973       4u,
974       4u,
975       glyphs02,
976       characterIndices,
977       charactersPerGlyph,
978       0u,
979       nullptr,
980       false,
981       fontDescriptions02
982     }
983   };
984
985   const unsigned int numberOfTests = 2u;
986
987   for( unsigned int index = 0u; index < numberOfTests; ++index )
988   {
989     ToolkitTestApplication application;
990     LoadSoftwareStylingFonts();
991
992     if( !ShapeInfoTest( data[index] ) )
993     {
994       tet_result(TET_FAIL);
995     }
996   }
997
998   tet_result(TET_PASS);
999   END_TEST;
1000 }
1001
1002
1003 int UtcDaliTextShapeEmojiSequences(void)
1004 {
1005
1006   ToolkitTestApplication application;
1007
1008   tet_infoline(" UtcDaliTextShapeEmojiSequences");
1009
1010   const std::string colorFontFamily( "NotoColorEmoji" );
1011   const std::string textFontFamily( "DejaVuSans" );
1012
1013   LoadEmojiFonts();
1014
1015   //Common attributes for font Descriptions
1016   CharacterRun    characterRun = {0u, 2u};
1017   FontWeight      weight       = TextAbstraction::FontWeight::NORMAL;
1018   FontWidth       width        = TextAbstraction::FontWidth::NORMAL;
1019   FontSlant       slant        = TextAbstraction::FontSlant::ITALIC;
1020   PointSize26Dot6 size         = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
1021
1022   bool familyDefined = true;
1023   bool weightDefined = false;
1024   bool widthDefined  = false;
1025   bool slantDefined  = false;
1026   bool sizeDefined   = false;
1027
1028
1029   // variation selector 16 (Emoji)
1030   struct GlyphInfoData glyphsVS16[] =
1031   {
1032     { 2u, 74u, 0.f, 0.f, 0.f, 0.f, 39.0f, 0.f, false, false },
1033   };
1034   CharacterIndex characterIndicesVS16[] = { 0u, 1u};
1035   Length charactersPerGlyphVS16[] = { 2u };
1036
1037
1038
1039   // variation selector 15 (Text)
1040   struct GlyphInfoData glyphsVS15[] =
1041   {
1042     { 1u, 3842u, 0.f, 0.f, 0.f, 0.f, 14.0f, 0.f, false, false },
1043     { 1u, 8203u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, false, false },
1044   };
1045   CharacterIndex characterIndicesVS15[] = { 0u, 0u};
1046   Length charactersPerGlyphVS15[] = { 0u, 2u };
1047
1048   //Font Descriptions
1049   Vector<FontDescriptionRun> fontDescriptionsColorVS16 =
1050                     CreateSingleFontDescription (characterRun, colorFontFamily, weight, width,
1051                      slant, size, familyDefined, weightDefined, widthDefined, slantDefined, sizeDefined);
1052
1053   Vector<FontDescriptionRun> fontDescriptionsColorVS15 =
1054                     CreateSingleFontDescription (characterRun, colorFontFamily, weight, width,
1055                      slant, size, familyDefined, weightDefined, widthDefined, slantDefined, sizeDefined);
1056
1057   Vector<FontDescriptionRun> fontDescriptionsTextVS16 =
1058                     CreateSingleFontDescription (characterRun, textFontFamily, weight, width,
1059                      slant, size, familyDefined, weightDefined, widthDefined, slantDefined, sizeDefined);
1060
1061   Vector<FontDescriptionRun> fontDescriptionsTextVS15 =
1062                     CreateSingleFontDescription (characterRun, textFontFamily, weight, width,
1063                      slant, size, familyDefined, weightDefined, widthDefined, slantDefined, sizeDefined);
1064
1065
1066   struct ShapeInfoData data[] =
1067   {
1068      {
1069       "EMOJI Sequence: Color Font with VS16",
1070       "&#x262a;&#xfe0f;",
1071       0u,
1072       2u,
1073       1u,
1074       glyphsVS16,
1075       characterIndicesVS16,
1076       charactersPerGlyphVS16,
1077       0u,
1078       nullptr,
1079       true,
1080       fontDescriptionsColorVS16
1081     },
1082     {
1083       "EMOJI Sequence: Color Font with VS15",
1084       "&#x262a;&#xfe0e;",
1085       0u,
1086       2u,
1087       2u,
1088       glyphsVS15,
1089       characterIndicesVS15,
1090       charactersPerGlyphVS15,
1091       0u,
1092       nullptr,
1093       true,
1094       fontDescriptionsColorVS15
1095     },
1096     {
1097       "EMOJI Sequence: Text Font with VS16",
1098       "&#x262a;&#xfe0f;",
1099       0u,
1100       2u,
1101       1u,
1102       glyphsVS16,
1103       characterIndicesVS16,
1104       charactersPerGlyphVS16,
1105       0u,
1106       nullptr,
1107       true,
1108       fontDescriptionsTextVS16
1109     },
1110     {
1111       "EMOJI Sequence: Text Font with VS15",
1112       "&#x262a;&#xfe0e;",
1113       0u,
1114       2u,
1115       2u,
1116       glyphsVS15,
1117       characterIndicesVS15,
1118       charactersPerGlyphVS15,
1119       0u,
1120       nullptr,
1121       true,
1122       fontDescriptionsTextVS15
1123     },
1124   };
1125
1126   const unsigned int numberOfTests = 4u;
1127
1128   for( unsigned int index = 0u; index < numberOfTests; ++index )
1129   {
1130      tet_infoline( data[index].description.c_str());
1131     if( !ShapeInfoTest( data[index] ) )
1132     {
1133       tet_result(TET_FAIL);
1134     }
1135   }
1136
1137   tet_result(TET_PASS);
1138   END_TEST;
1139 }