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