[dali_2.1.24] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-Text-Shaping.cpp
1 /*
2  * Copyright (c) 2022 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 <stdlib.h>
19 #include <unistd.h>
20 #include <iostream>
21
22 #include <dali-toolkit-test-suite-utils.h>
23 #include <dali-toolkit/dali-toolkit.h>
24 #include <dali-toolkit/internal/text/shaper.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.0f, // lineSpacing
149                   0.0f  // characterSpacing
150   );
151
152   LogicalModelPtr logicalModel = textModel->mLogicalModel;
153   VisualModelPtr  visualModel  = textModel->mVisualModel;
154
155   // 2) Clear the model.
156
157   Vector<GlyphInfo>&      glyphs             = visualModel->mGlyphs;
158   Vector<CharacterIndex>& glyphToCharacter   = visualModel->mGlyphsToCharacters;
159   Vector<Length>&         charactersPerGlyph = visualModel->mCharactersPerGlyph;
160   Vector<GlyphIndex>&     charactersToGlyph  = visualModel->mCharactersToGlyph;
161   Vector<Length>&         glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
162
163   // Get the glyph index.
164   GlyphIndex glyphIndex = 0u;
165   if(0u != visualModel->mCharactersToGlyph.Count())
166   {
167     glyphIndex = *(visualModel->mCharactersToGlyph.Begin() + data.index);
168
169     const CharacterIndex lastCharacterIndex = data.index + data.numberOfCharacters - 1u;
170     const Length         numberOfGlyphs     = *(visualModel->mCharactersToGlyph.Begin() + lastCharacterIndex) + *(visualModel->mGlyphsPerCharacter.Begin() + lastCharacterIndex) - glyphIndex;
171
172     // Erase the glyph info from the text model.
173     // Got from the ShapeText() function.
174     glyphs.Erase(glyphs.Begin() + glyphIndex, glyphs.Begin() + glyphIndex + numberOfGlyphs);
175     glyphToCharacter.Erase(glyphToCharacter.Begin() + glyphIndex, glyphToCharacter.Begin() + glyphIndex + numberOfGlyphs);
176     charactersPerGlyph.Erase(charactersPerGlyph.Begin() + glyphIndex, charactersPerGlyph.Begin() + glyphIndex + numberOfGlyphs);
177
178     // Got from the VisualModel::CreateCharacterToGlyphTable() and the VisualModel::CreateGlyphsPerCharacterTable() methods.
179     charactersToGlyph.Erase(charactersToGlyph.Begin() + data.index,
180                             charactersToGlyph.Begin() + data.index + data.numberOfCharacters);
181     glyphsPerCharacter.Erase(glyphsPerCharacter.Begin() + data.index,
182                              glyphsPerCharacter.Begin() + data.index + data.numberOfCharacters);
183
184     // Update the glyph to character indices.
185     for(Vector<CharacterIndex>::Iterator it    = glyphToCharacter.Begin() + glyphIndex,
186                                          endIt = glyphToCharacter.End();
187         it != endIt;
188         ++it)
189     {
190       CharacterIndex& index = *it;
191       index -= data.numberOfCharacters;
192     }
193   }
194
195   // Reset the metrics got from the model as the ShapeText() function doesn't retrieve them.
196   for(Vector<GlyphInfo>::Iterator it    = glyphs.Begin(),
197                                   endIt = glyphs.End();
198       it != endIt;
199       ++it)
200   {
201     GlyphInfo& info  = *it;
202     info.width       = 0.f;
203     info.height      = 0.f;
204     info.xBearing    = 0.f;
205     info.yBearing    = 0.f;
206     info.scaleFactor = 0.f;
207   }
208
209   // 3) Call the ShapeText() function.
210
211   Vector<GlyphIndex> newParagraphGlyphs;
212
213   ShapeText(logicalModel->mText,
214             logicalModel->mLineBreakInfo,
215             logicalModel->mScriptRuns,
216             logicalModel->mFontRuns,
217             data.index,
218             glyphIndex,
219             data.numberOfCharacters,
220             glyphs,
221             glyphToCharacter,
222             charactersPerGlyph,
223             newParagraphGlyphs);
224
225   // Clear the advance of the new paragraph glyphs.
226   for(Vector<GlyphIndex>::Iterator it    = newParagraphGlyphs.Begin(),
227                                    endIt = newParagraphGlyphs.End();
228       it != endIt;
229       ++it)
230   {
231     GlyphInfo& info = *(glyphs.Begin() + *it);
232     info.advance    = 0.f;
233   }
234
235   // 4) Compare the results.
236
237   if(data.expectedNumberOfGlyphs != glyphs.Count())
238   {
239     std::cout << "  Different number of glyphs : " << glyphs.Count() << ", expected : " << data.expectedNumberOfGlyphs << std::endl;
240     return false;
241   }
242
243   for(unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index)
244   {
245     if(!IsEqualGlyph(data.glyphs[index], glyphs[index]))
246     {
247       std::cout << "  different glyph info, index : " << index << std::endl;
248
249       const GlyphInfo& glyphInfo = glyphs[index];
250       std::cout << "            fontId : " << glyphInfo.fontId << std::endl;
251       std::cout << "             index : " << glyphInfo.index << std::endl;
252       std::cout << "             width : " << glyphInfo.width << std::endl;
253       std::cout << "            height : " << glyphInfo.height << std::endl;
254       std::cout << "          xBearing : " << glyphInfo.xBearing << std::endl;
255       std::cout << "          yBearing : " << glyphInfo.yBearing << std::endl;
256       std::cout << "           advance : " << floor(glyphInfo.advance) << std::endl;
257       std::cout << "       scaleFactor : " << glyphInfo.scaleFactor << std::endl;
258       std::cout << "  isItalicRequired : " << glyphInfo.isItalicRequired << std::endl;
259       std::cout << "    isBoldRequired : " << glyphInfo.isBoldRequired << std::endl;
260
261       std::cout << "  Expected : " << std::endl;
262       const GlyphInfoData& expectedGlyphInfo = data.glyphs[index];
263       std::cout << "            fontId : " << expectedGlyphInfo.fontId << std::endl;
264       std::cout << "             index : " << expectedGlyphInfo.index << std::endl;
265       std::cout << "             width : " << expectedGlyphInfo.width << std::endl;
266       std::cout << "            height : " << expectedGlyphInfo.height << std::endl;
267       std::cout << "          xBearing : " << expectedGlyphInfo.xBearing << std::endl;
268       std::cout << "          yBearing : " << expectedGlyphInfo.yBearing << std::endl;
269       std::cout << "           advance : " << expectedGlyphInfo.advance << std::endl;
270       std::cout << "       scaleFactor : " << expectedGlyphInfo.scaleFactor << std::endl;
271       std::cout << "  isItalicRequired : " << expectedGlyphInfo.isItalicRequired << std::endl;
272       std::cout << "    isBoldRequired : " << expectedGlyphInfo.isBoldRequired << std::endl;
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   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, 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u, 21u, 22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 37u, 38u, 39u, 40u, 41u, 42u, 43u, 44u, 45u, 46u, 47u, 48u, 49u, 50u, 51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 66u, 67u, 68u, 69u, 70u, 71u, 72u, 73u, 74u};
518   Length         charactersPerGlyph05[] = {1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 2u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u};
519   CharacterIndex newParagraphGlyphs05[] = {26u};
520   CharacterIndex newParagraphGlyphs06[] = {49u};
521   CharacterIndex newParagraphGlyphs07[] = {73u};
522
523   Vector<FontDescriptionRun> fontDescriptions01;
524   Vector<FontDescriptionRun> fontDescriptions02;
525   Vector<FontDescriptionRun> fontDescriptions03;
526   Vector<FontDescriptionRun> fontDescriptions04;
527   Vector<FontDescriptionRun> fontDescriptions05;
528   Vector<FontDescriptionRun> fontDescriptions06;
529
530   const std::string fontFamily("TizenSans");
531   const std::string fontFamilyMalayalam("Noto Sans Malayalam");
532
533   FontDescriptionRun fontDescriptionRun01 =
534     {
535       {0u,
536        11u},
537       nullptr,
538       0u,
539       TextAbstraction::FontWeight::NONE,
540       TextAbstraction::FontWidth::NONE,
541       TextAbstraction::FontSlant::NONE,
542       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
543       true,
544       false,
545       false,
546       false,
547       false};
548   fontDescriptionRun01.familyLength = fontFamily.size();
549   fontDescriptionRun01.familyName   = new char[fontDescriptionRun01.familyLength];
550   memcpy(fontDescriptionRun01.familyName, fontFamily.c_str(), fontDescriptionRun01.familyLength);
551
552   fontDescriptions01.PushBack(fontDescriptionRun01);
553
554   FontDescriptionRun fontDescriptionRun02 =
555     {
556       {0u,
557        17u},
558       nullptr,
559       0u,
560       TextAbstraction::FontWeight::NONE,
561       TextAbstraction::FontWidth::NONE,
562       TextAbstraction::FontSlant::NONE,
563       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
564       true,
565       false,
566       false,
567       false,
568       false};
569   fontDescriptionRun02.familyLength = fontFamily.size();
570   fontDescriptionRun02.familyName   = new char[fontDescriptionRun02.familyLength];
571   memcpy(fontDescriptionRun02.familyName, fontFamily.c_str(), fontDescriptionRun02.familyLength);
572
573   fontDescriptions02.PushBack(fontDescriptionRun02);
574
575   FontDescriptionRun fontDescriptionRun03 =
576     {
577       {0u,
578        8u},
579       nullptr,
580       0u,
581       TextAbstraction::FontWeight::NONE,
582       TextAbstraction::FontWidth::NONE,
583       TextAbstraction::FontSlant::NONE,
584       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
585       true,
586       false,
587       false,
588       false,
589       false};
590   fontDescriptionRun03.familyLength = fontFamilyMalayalam.size();
591   fontDescriptionRun03.familyName   = new char[fontDescriptionRun03.familyLength];
592   memcpy(fontDescriptionRun03.familyName, fontFamilyMalayalam.c_str(), fontDescriptionRun03.familyLength);
593
594   fontDescriptions03.PushBack(fontDescriptionRun03);
595
596   FontDescriptionRun fontDescriptionRun04 =
597     {
598       {0u,
599        75u},
600       nullptr,
601       0u,
602       TextAbstraction::FontWeight::NONE,
603       TextAbstraction::FontWidth::NONE,
604       TextAbstraction::FontSlant::NONE,
605       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
606       true,
607       false,
608       false,
609       false,
610       false};
611   fontDescriptionRun04.familyLength = fontFamily.size();
612   fontDescriptionRun04.familyName   = new char[fontDescriptionRun04.familyLength];
613   memcpy(fontDescriptionRun04.familyName, fontFamily.c_str(), fontDescriptionRun04.familyLength);
614
615   fontDescriptions04.PushBack(fontDescriptionRun04);
616
617   FontDescriptionRun fontDescriptionRun05 =
618     {
619       {0u,
620        75u},
621       nullptr,
622       0u,
623       TextAbstraction::FontWeight::NONE,
624       TextAbstraction::FontWidth::NONE,
625       TextAbstraction::FontSlant::NONE,
626       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
627       true,
628       false,
629       false,
630       false,
631       false};
632   fontDescriptionRun05.familyLength = fontFamily.size();
633   fontDescriptionRun05.familyName   = new char[fontDescriptionRun05.familyLength];
634   memcpy(fontDescriptionRun05.familyName, fontFamily.c_str(), fontDescriptionRun05.familyLength);
635
636   fontDescriptions05.PushBack(fontDescriptionRun05);
637
638   FontDescriptionRun fontDescriptionRun06 =
639     {
640       {0u,
641        75u},
642       nullptr,
643       0u,
644       TextAbstraction::FontWeight::NONE,
645       TextAbstraction::FontWidth::NONE,
646       TextAbstraction::FontSlant::NONE,
647       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
648       true,
649       false,
650       false,
651       false,
652       false};
653   fontDescriptionRun06.familyLength = fontFamily.size();
654   fontDescriptionRun06.familyName   = new char[fontDescriptionRun06.familyLength];
655   memcpy(fontDescriptionRun06.familyName, fontFamily.c_str(), fontDescriptionRun06.familyLength);
656
657   fontDescriptions06.PushBack(fontDescriptionRun06);
658
659   struct ShapeInfoData data[] =
660     {
661       {
662         "Zero characters",
663         "",
664         0u,
665         0u,
666         0u,
667         nullptr,
668         nullptr,
669         nullptr,
670         0u,
671         nullptr,
672         false,
673       },
674       {"Latin script",
675        "Hello world",
676        0u,
677        11u,
678        11u,
679        glyphs02,
680        characterIndices02,
681        charactersPerGlyph02,
682        0u,
683        nullptr,
684        false,
685        fontDescriptions01},
686       {"Latin script. Some paragraphs.",
687        "Hello world\ndemo\n",
688        0u,
689        17u,
690        17u,
691        glyphs03,
692        characterIndices03,
693        charactersPerGlyph03,
694        2u,
695        newParagraphGlyphs03,
696        false,
697        fontDescriptions02},
698       {"Malayalam script. More glyphs than characters.",
699        "ജോസോഹോവോ",
700        0u,
701        8u,
702        12u,
703        glyphs04,
704        characterIndices04,
705        charactersPerGlyph04,
706        0u,
707        nullptr,
708        false,
709        fontDescriptions03},
710       {
711         "Latin script with some paragraphs. Update initial paragraph.",
712         "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
713         0u,
714         27u,
715         74u,
716         glyphs05,
717         characterIndices05,
718         charactersPerGlyph05,
719         1u,
720         newParagraphGlyphs05,
721         false,
722         fontDescriptions04,
723       },
724       {"Latin script with some paragraphs. Update mid paragraph.",
725        "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
726        27u,
727        24u,
728        74u,
729        glyphs05,
730        characterIndices05,
731        charactersPerGlyph05,
732        1u,
733        newParagraphGlyphs06,
734        false,
735        fontDescriptions05},
736       {"Latin script with some paragraphs. Update final paragraph.",
737        "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
738        51u,
739        24u,
740        74u,
741        glyphs05,
742        characterIndices05,
743        charactersPerGlyph05,
744        1u,
745        newParagraphGlyphs07,
746        false,
747        fontDescriptions06},
748     };
749   const unsigned int numberOfTests = 7u;
750
751   for(unsigned int index = 0u; index < numberOfTests; ++index)
752   {
753     ToolkitTestApplication application;
754     LoadTextShapeFonts();
755
756     if(!ShapeInfoTest(data[index]))
757     {
758       tet_result(TET_FAIL);
759     }
760   }
761
762   tet_result(TET_PASS);
763   END_TEST;
764 }
765
766 int UtcDaliTextSoftwareStyling(void)
767 {
768   tet_infoline(" UtcDaliTextSoftwareStyling");
769
770   struct GlyphInfoData glyphs01[] =
771     {
772       {4u, 38u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, true, true},
773       {4u, 39u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f, true, true},
774       {4u, 40u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, true, true},
775       {4u, 41u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, true, true},
776     };
777   struct GlyphInfoData glyphs02[] =
778     {
779       {1u, 38u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, false, false},
780       {2u, 39u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, false, true},
781       {3u, 40u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, true, false},
782       {4u, 41u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f, true, true},
783     };
784
785   CharacterIndex characterIndices[]   = {0u, 1u, 2u, 3u};
786   Length         charactersPerGlyph[] = {1u, 1u, 1u, 1u};
787
788   Vector<FontDescriptionRun> fontDescriptions01;
789   Vector<FontDescriptionRun> fontDescriptions02;
790
791   const std::string fontFamily("Roboto");
792
793   FontDescriptionRun fontDescriptionRun01 =
794     {
795       {0u,
796        4u},
797       nullptr,
798       0u,
799       TextAbstraction::FontWeight::BOLD,
800       TextAbstraction::FontWidth::NONE,
801       TextAbstraction::FontSlant::ITALIC,
802       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
803       true,
804       true,
805       false,
806       true,
807       false};
808   fontDescriptionRun01.familyLength = fontFamily.size();
809   fontDescriptionRun01.familyName   = new char[fontDescriptionRun01.familyLength];
810   memcpy(fontDescriptionRun01.familyName, fontFamily.c_str(), fontDescriptionRun01.familyLength);
811
812   fontDescriptions01.PushBack(fontDescriptionRun01);
813
814   FontDescriptionRun fontDescriptionRun02 =
815     {
816       {0u,
817        1u},
818       nullptr,
819       0u,
820       TextAbstraction::FontWeight::NONE,
821       TextAbstraction::FontWidth::NONE,
822       TextAbstraction::FontSlant::NONE,
823       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
824       true,
825       false,
826       false,
827       false,
828       false};
829   fontDescriptionRun02.familyLength = fontFamily.size();
830   fontDescriptionRun02.familyName   = new char[fontDescriptionRun02.familyLength];
831   memcpy(fontDescriptionRun02.familyName, fontFamily.c_str(), fontDescriptionRun02.familyLength);
832
833   FontDescriptionRun fontDescriptionRun03 =
834     {
835       {1u,
836        1u},
837       nullptr,
838       0u,
839       TextAbstraction::FontWeight::BOLD,
840       TextAbstraction::FontWidth::NONE,
841       TextAbstraction::FontSlant::NONE,
842       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
843       true,
844       true,
845       false,
846       false,
847       false};
848   fontDescriptionRun03.familyLength = fontFamily.size();
849   fontDescriptionRun03.familyName   = new char[fontDescriptionRun03.familyLength];
850   memcpy(fontDescriptionRun03.familyName, fontFamily.c_str(), fontDescriptionRun03.familyLength);
851
852   FontDescriptionRun fontDescriptionRun04 =
853     {
854       {2u,
855        1u},
856       nullptr,
857       0u,
858       TextAbstraction::FontWeight::NONE,
859       TextAbstraction::FontWidth::NONE,
860       TextAbstraction::FontSlant::ITALIC,
861       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
862       true,
863       false,
864       false,
865       true,
866       false};
867   fontDescriptionRun04.familyLength = fontFamily.size();
868   fontDescriptionRun04.familyName   = new char[fontDescriptionRun04.familyLength];
869   memcpy(fontDescriptionRun04.familyName, fontFamily.c_str(), fontDescriptionRun04.familyLength);
870
871   FontDescriptionRun fontDescriptionRun05 =
872     {
873       {3u,
874        1u},
875       nullptr,
876       0u,
877       TextAbstraction::FontWeight::BOLD,
878       TextAbstraction::FontWidth::NONE,
879       TextAbstraction::FontSlant::ITALIC,
880       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
881       true,
882       true,
883       false,
884       true,
885       false};
886   fontDescriptionRun05.familyLength = fontFamily.size();
887   fontDescriptionRun05.familyName   = new char[fontDescriptionRun05.familyLength];
888   memcpy(fontDescriptionRun05.familyName, fontFamily.c_str(), fontDescriptionRun05.familyLength);
889
890   fontDescriptions02.PushBack(fontDescriptionRun02);
891   fontDescriptions02.PushBack(fontDescriptionRun03);
892   fontDescriptions02.PushBack(fontDescriptionRun04);
893   fontDescriptions02.PushBack(fontDescriptionRun05);
894
895   struct ShapeInfoData data[] =
896     {
897       {"Latin script. Characters have same font description",
898        "ABCD",
899        0u,
900        4u,
901        4u,
902        glyphs01,
903        characterIndices,
904        charactersPerGlyph,
905        0u,
906        nullptr,
907        false,
908        fontDescriptions01},
909       {"Latin script. Each character has different font description.",
910        "ABCD",
911        0u,
912        4u,
913        4u,
914        glyphs02,
915        characterIndices,
916        charactersPerGlyph,
917        0u,
918        nullptr,
919        false,
920        fontDescriptions02}};
921
922   const unsigned int numberOfTests = 2u;
923
924   for(unsigned int index = 0u; index < numberOfTests; ++index)
925   {
926     ToolkitTestApplication application;
927     LoadSoftwareStylingFonts();
928
929     if(!ShapeInfoTest(data[index]))
930     {
931       tet_result(TET_FAIL);
932     }
933   }
934
935   tet_result(TET_PASS);
936   END_TEST;
937 }
938
939 int UtcDaliTextShapeEmojiSequences(void)
940 {
941   ToolkitTestApplication application;
942
943   tet_infoline(" UtcDaliTextShapeEmojiSequences");
944
945   const std::string colorFontFamily("NotoColorEmoji");
946   const std::string textFontFamily("DejaVuSans");
947
948   LoadEmojiFonts();
949
950   //Common attributes for font Descriptions
951   CharacterRun    characterRun = {0u, 2u};
952   FontWeight      weight       = TextAbstraction::FontWeight::NORMAL;
953   FontWidth       width        = TextAbstraction::FontWidth::NORMAL;
954   FontSlant       slant        = TextAbstraction::FontSlant::ITALIC;
955   PointSize26Dot6 size         = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
956
957   bool familyDefined = true;
958   bool weightDefined = false;
959   bool widthDefined  = false;
960   bool slantDefined  = false;
961   bool sizeDefined   = false;
962
963   // variation selector 16 (Emoji)
964   struct GlyphInfoData glyphsVS16[] =
965     {
966       {2u, 74u, 0.f, 0.f, 0.f, 0.f, 39.0f, 0.f, false, false},
967     };
968   CharacterIndex characterIndicesVS16[]   = {0u, 1u};
969   Length         charactersPerGlyphVS16[] = {2u};
970
971   // variation selector 15 (Text)
972   struct GlyphInfoData glyphsVS15[] =
973     {
974       {1u, 3842u, 0.f, 0.f, 0.f, 0.f, 14.0f, 0.f, false, false},
975       {1u, 8203u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, false, false},
976     };
977   CharacterIndex characterIndicesVS15[]   = {0u, 0u};
978   Length         charactersPerGlyphVS15[] = {0u, 2u};
979
980   //Font Descriptions
981   Vector<FontDescriptionRun> fontDescriptionsColorVS16 =
982     CreateSingleFontDescription(characterRun, colorFontFamily, weight, width, slant, size, familyDefined, weightDefined, widthDefined, slantDefined, sizeDefined);
983
984   Vector<FontDescriptionRun> fontDescriptionsColorVS15 =
985     CreateSingleFontDescription(characterRun, colorFontFamily, weight, width, slant, size, familyDefined, weightDefined, widthDefined, slantDefined, sizeDefined);
986
987   Vector<FontDescriptionRun> fontDescriptionsTextVS16 =
988     CreateSingleFontDescription(characterRun, textFontFamily, weight, width, slant, size, familyDefined, weightDefined, widthDefined, slantDefined, sizeDefined);
989
990   Vector<FontDescriptionRun> fontDescriptionsTextVS15 =
991     CreateSingleFontDescription(characterRun, textFontFamily, weight, width, slant, size, familyDefined, weightDefined, widthDefined, slantDefined, sizeDefined);
992
993   struct ShapeInfoData data[] =
994     {
995       {"EMOJI Sequence: Color Font with VS16",
996        "&#x262a;&#xfe0f;",
997        0u,
998        2u,
999        1u,
1000        glyphsVS16,
1001        characterIndicesVS16,
1002        charactersPerGlyphVS16,
1003        0u,
1004        nullptr,
1005        true,
1006        fontDescriptionsColorVS16},
1007       {"EMOJI Sequence: Color Font with VS15",
1008        "&#x262a;&#xfe0e;",
1009        0u,
1010        2u,
1011        2u,
1012        glyphsVS15,
1013        characterIndicesVS15,
1014        charactersPerGlyphVS15,
1015        0u,
1016        nullptr,
1017        true,
1018        fontDescriptionsColorVS15},
1019       {"EMOJI Sequence: Text Font with VS16",
1020        "&#x262a;&#xfe0f;",
1021        0u,
1022        2u,
1023        1u,
1024        glyphsVS16,
1025        characterIndicesVS16,
1026        charactersPerGlyphVS16,
1027        0u,
1028        nullptr,
1029        true,
1030        fontDescriptionsTextVS16},
1031       {"EMOJI Sequence: Text Font with VS15",
1032        "&#x262a;&#xfe0e;",
1033        0u,
1034        2u,
1035        2u,
1036        glyphsVS15,
1037        characterIndicesVS15,
1038        charactersPerGlyphVS15,
1039        0u,
1040        nullptr,
1041        true,
1042        fontDescriptionsTextVS15},
1043     };
1044
1045   const unsigned int numberOfTests = 4u;
1046
1047   for(unsigned int index = 0u; index < numberOfTests; ++index)
1048   {
1049     tet_infoline(data[index].description.c_str());
1050     if(!ShapeInfoTest(data[index]))
1051     {
1052       tet_result(TET_FAIL);
1053     }
1054   }
1055
1056   tet_result(TET_PASS);
1057   END_TEST;
1058 }