0dd3144787334bc90f05cb12cae20c7c553030f9
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-Text-Shaping.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <iostream>
19 #include <stdlib.h>
20
21 #include <dali-toolkit/internal/text/shaper.h>
22 #include <dali-toolkit-test-suite-utils.h>
23 #include <dali-toolkit/dali-toolkit.h>
24 #include <toolkit-text-model.h>
25
26 using namespace Dali;
27 using namespace Toolkit;
28 using namespace Text;
29
30 // Tests the following function.
31 // void ShapeText( const Vector<Character>& text,
32 //                 const Vector<LineBreakInfo>& lineBreakInfo,
33 //                 const Vector<ScriptRun>& scripts,
34 //                 const Vector<FontRun>& fonts,
35 //                 CharacterIndex startCharacterIndex,
36 //                 GlyphIndex startGlyphIndex,
37 //                 Length numberOfCharacters,
38 //                 Vector<GlyphInfo>& glyphs,
39 //                 Vector<CharacterIndex>& glyphToCharacterMap,
40 //                 Vector<Length>& charactersPerGlyph,
41 //                 Vector<GlyphIndex>& newParagraphGlyphs );
42
43 //////////////////////////////////////////////////////////
44
45 namespace
46 {
47
48 struct GlyphInfoData
49 {
50   FontId fontId;     ///< Identifies the font containing the glyph
51   GlyphIndex index;  ///< Uniquely identifies a glyph for a given FontId
52   float width;       ///< The width of the glyph
53   float height;      ///< The height of the glyph
54   float xBearing;    ///< The distance from the cursor position to the leftmost border of the glyph
55   float yBearing;    ///< The distance from the baseline to the topmost border of the glyph
56   float advance;     ///< The distance to move the cursor for this glyph
57   float scaleFactor; ///< The scaling applied (fixed-size fonts only)
58 };
59
60 bool IsEqualGlyph ( const GlyphInfoData& glyphData, const GlyphInfo& glyph )
61 {
62   if( glyphData.fontId != glyph.fontId )
63   {
64     return false;
65   }
66   if( glyphData.index != glyph.index )
67   {
68     return false;
69   }
70   if( fabsf( glyphData.width - glyph.width ) > Math::MACHINE_EPSILON_1000 )
71   {
72     return false;
73   }
74   if( fabsf( glyphData.height - glyph.height ) > Math::MACHINE_EPSILON_1000 )
75   {
76     return false;
77   }
78   if( fabsf( glyphData.xBearing - glyph.xBearing ) > Math::MACHINE_EPSILON_1000 )
79   {
80     return false;
81   }
82   if( fabsf( glyphData.yBearing - glyph.yBearing ) > Math::MACHINE_EPSILON_1000 )
83   {
84     return false;
85   }
86   if( fabsf( glyphData.advance - glyph.advance ) > Math::MACHINE_EPSILON_1000 )
87   {
88     return false;
89   }
90   if( fabsf( glyphData.scaleFactor - glyph.scaleFactor ) > Math::MACHINE_EPSILON_1000 )
91   {
92     return false;
93   }
94
95   return true;
96 }
97
98 struct ShapeInfoData
99 {
100   std::string     description;                        ///< Description of the test.
101   std::string     text;                               ///< input text.
102   uint32_t        index;                              ///< The index from where to start to query the break info.
103   uint32_t        numberOfCharacters;                 ///< The requested number of characters.
104   uint32_t        expectedNumberOfGlyphs;             ///< The expected number of glyphs.
105   GlyphInfoData*  glyphs;                             ///< The glyphs.
106   CharacterIndex* characterIndices;                   ///< The character index for each glyph.
107   Length*         charactersPerGlyph;                 ///< The characters per glyph.
108   uint32_t        expectedNumberOfNewParagraphGlyphs; ///< The expected number of glyphs.
109   GlyphIndex*     newParagraphGlyphs;                 ///< Indices to the new paragraphs glyphs.
110 };
111
112 bool ShapeInfoTest( const ShapeInfoData& data )
113 {
114   // 1) Create the model.
115   LogicalModelPtr logicalModel = LogicalModel::New();
116   VisualModelPtr visualModel = VisualModel::New();
117   Size textArea(100.f, 60.f);
118   Size layoutSize;
119
120   CreateTextModel( data.text,
121                    textArea,
122                    layoutSize,
123                    logicalModel,
124                    visualModel );
125
126   // 2) Clear the model.
127
128   Vector<GlyphInfo>& glyphs = visualModel->mGlyphs;
129   Vector<CharacterIndex>& glyphToCharacter = visualModel->mGlyphsToCharacters;
130   Vector<Length>& charactersPerGlyph = visualModel->mCharactersPerGlyph;
131   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
132   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
133
134   // Get the glyph index.
135   GlyphIndex glyphIndex = 0u;
136   if( 0u != visualModel->mCharactersToGlyph.Count() )
137   {
138     glyphIndex = *( visualModel->mCharactersToGlyph.Begin() + data.index );
139
140     const CharacterIndex lastCharacterIndex = data.index + data.numberOfCharacters - 1u;
141     const Length numberOfGlyphs = *( visualModel->mCharactersToGlyph.Begin() + lastCharacterIndex ) + *( visualModel->mGlyphsPerCharacter.Begin() + lastCharacterIndex ) - glyphIndex;
142
143     // Erase the glyph info from the text model.
144     // Got from the ShapeText() function.
145     glyphs.Erase( glyphs.Begin() + glyphIndex, glyphs.Begin() + glyphIndex + numberOfGlyphs );
146     glyphToCharacter.Erase( glyphToCharacter.Begin() + glyphIndex, glyphToCharacter.Begin() + glyphIndex + numberOfGlyphs );
147     charactersPerGlyph.Erase( charactersPerGlyph.Begin() + glyphIndex, charactersPerGlyph.Begin() + glyphIndex + numberOfGlyphs );
148
149     // Got from the VisualModel::CreateCharacterToGlyphTable() and the VisualModel::CreateGlyphsPerCharacterTable() methods.
150     charactersToGlyph.Erase( charactersToGlyph.Begin() + data.index,
151                              charactersToGlyph.Begin() + data.index + data.numberOfCharacters );
152     glyphsPerCharacter.Erase( glyphsPerCharacter.Begin() + data.index,
153                               glyphsPerCharacter.Begin() + data.index + data.numberOfCharacters );
154
155     // Update the glyph to character indices.
156     for( Vector<CharacterIndex>::Iterator it = glyphToCharacter.Begin() + glyphIndex,
157            endIt = glyphToCharacter.End();
158          it != endIt;
159          ++it )
160     {
161       CharacterIndex& index = *it;
162       index -= data.numberOfCharacters;
163     }
164
165   }
166
167   // Reset the metrics got from the model as the ShapeText() function doesn't retrieve them.
168   for( Vector<GlyphInfo>::Iterator it = glyphs.Begin(),
169          endIt = glyphs.End();
170        it != endIt;
171        ++it )
172   {
173     GlyphInfo& info = *it;
174     info.width = 0.f;
175     info.height = 0.f;
176     info.xBearing = 0.f;
177     info.yBearing = 0.f;
178     info.scaleFactor = 0.f;
179   }
180
181   // 3) Call the ShapeText() function.
182
183   Vector<GlyphIndex> newParagraphGlyphs;
184
185   ShapeText( logicalModel->mText,
186              logicalModel->mLineBreakInfo,
187              logicalModel->mScriptRuns,
188              logicalModel->mFontRuns,
189              data.index,
190              glyphIndex,
191              data.numberOfCharacters,
192              glyphs,
193              glyphToCharacter,
194              charactersPerGlyph,
195              newParagraphGlyphs );
196
197   // Clear the advance of the new paragraph glyphs.
198   for( Vector<GlyphIndex>::Iterator it = newParagraphGlyphs.Begin(),
199          endIt = newParagraphGlyphs.End();
200        it != endIt;
201        ++it )
202   {
203     GlyphInfo& info = *( glyphs.Begin() + *it );
204     info.advance = 0.f;
205   }
206
207   // 4) Compare the results.
208
209   if( data.expectedNumberOfGlyphs != glyphs.Count() )
210   {
211     std::cout << "  Different number of glyphs : " << glyphs.Count() << ", expected : " << data.expectedNumberOfGlyphs << std::endl;
212     return false;
213   }
214
215   for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
216   {
217     if( !IsEqualGlyph( data.glyphs[index], glyphs[index] ) )
218     {
219       std::cout << "  different glyph info, index : " << index << std::endl;
220       return false;
221     }
222   }
223
224   for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
225   {
226     if( data.characterIndices[index] != glyphToCharacter[index] )
227     {
228       std::cout << "  different character index, index : " << index << std::endl;
229       return false;
230     }
231   }
232
233   for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
234   {
235     if( data.charactersPerGlyph[index] != charactersPerGlyph[index] )
236     {
237       std::cout << "  different character per glyph, index : " << index << std::endl;
238       return false;
239     }
240   }
241
242   if( data.expectedNumberOfNewParagraphGlyphs != newParagraphGlyphs.Count() )
243   {
244     std::cout << "  Different number of new paragraph glyphs : " << newParagraphGlyphs.Count() << ", expected : " << data.expectedNumberOfNewParagraphGlyphs << std::endl;
245     return false;
246   }
247
248   for( unsigned int index = 0u; index < data.expectedNumberOfNewParagraphGlyphs; ++index )
249   {
250     if( data.newParagraphGlyphs[index] != newParagraphGlyphs[index] )
251     {
252       std::cout << "  different new paragraph glyph, index : " << index << std::endl;
253       return false;
254     }
255   }
256
257   return true;
258 }
259
260 } // namespace
261
262 //////////////////////////////////////////////////////////
263
264 int UtcDaliTextShape(void)
265 {
266   ToolkitTestApplication application;
267   tet_infoline(" UtcDaliTextShape");
268
269   struct GlyphInfoData glyphs02[] =
270   {
271     { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
272     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
273     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
274     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
275     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
276     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
277     { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
278     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
279     { 1u, 85u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
280     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
281     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
282   };
283
284   CharacterIndex characterIndices02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
285   Length charactersPerGlyph02[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
286
287   struct GlyphInfoData glyphs03[] =
288   {
289     { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
290     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
291     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
292     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
293     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
294     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
295     { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
296     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
297     { 1u, 85u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
298     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
299     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
300     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
301     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
302     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
303     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
304     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
305     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
306   };
307
308   CharacterIndex characterIndices03[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u };
309   Length charactersPerGlyph03[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
310   CharacterIndex newParagraphGlyphs03[] = { 11u, 16u };
311
312   struct GlyphInfoData glyphs04[] =
313   {
314     { 2u, 160u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
315     { 2u, 123u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
316     { 2u, 153u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
317     { 2u, 160u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
318     { 2u, 150u, 0.f, 0.f, 0.f, 0.f, 14.f, 0.f },
319     { 2u, 153u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
320     { 2u, 160u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
321     { 2u, 151u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
322     { 2u, 153u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
323     { 2u, 160u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
324     { 2u, 147u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
325     { 2u, 153u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
326   };
327
328   CharacterIndex characterIndices04[] = { 0u, 0u, 0u, 2u, 2u, 2u, 4u, 4u, 4u, 6u, 6u, 6u };
329   Length charactersPerGlyph04[] = { 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u };
330
331   struct GlyphInfoData glyphs05[] =
332   {
333     { 1u, 47u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
334     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
335     { 1u, 85u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
336     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
337     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
338     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
339     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
340     { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
341     { 1u, 86u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
342     { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
343     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
344     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
345     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
346     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
347     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
348     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
349     { 1u, 85u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
350     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
351     { 1u, 86u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
352     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
353     { 1u, 87u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
354     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
355     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
356     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
357     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
358     { 1u, 87u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
359     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
360     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
361     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
362     { 1u, 84u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
363     { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
364     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
365     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
366     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
367     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
368     { 1u, 5034u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
369     { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
370     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
371     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
372     { 1u, 69u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
373     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
374     { 1u, 86u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
375     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
376     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
377     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
378     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
379     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
380     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
381     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
382     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
383     { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
384     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
385     { 1u, 86u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
386     { 1u, 86u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
387     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
388     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
389     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
390     { 1u, 85u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
391     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
392     { 1u, 70u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
393     { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
394     { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
395     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
396     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
397     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
398     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
399     { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
400     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
401     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
402     { 1u, 70u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
403     { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
404     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
405     { 1u, 17u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
406     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
407   };
408
409   CharacterIndex characterIndices05[] = {  0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u,
410                                           10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u,
411                                           20u, 21u, 22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u,
412                                           30u, 31u, 32u, 33u, 34u, 35u, 37u, 38u, 39u, 40u,
413                                           41u, 42u, 43u, 44u, 45u, 46u, 47u, 48u, 49u, 50u,
414                                           51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u,
415                                           61u, 62u, 63u, 64u, 65u, 66u, 67u, 68u, 69u, 70u,
416                                           71u, 72u, 73u, 74u };
417   Length charactersPerGlyph05[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
418                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
419                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
420                                     1u, 1u, 1u, 1u, 1u, 2u, 1u, 1u, 1u, 1u,
421                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
422                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
423                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
424                                     1u, 1u, 1u, 1u };
425   CharacterIndex newParagraphGlyphs05[] = { 26u };
426   CharacterIndex newParagraphGlyphs06[] = { 49u };
427   CharacterIndex newParagraphGlyphs07[] = { 73u };
428
429   struct ShapeInfoData data[] =
430   {
431     {
432       "Zero characters",
433       "",
434       0u,
435       0u,
436       0u,
437       NULL,
438       NULL,
439       NULL,
440       0u,
441       NULL
442     },
443     {
444       "Latin script",
445       "Hello world",
446       0u,
447       11u,
448       11u,
449       glyphs02,
450       characterIndices02,
451       charactersPerGlyph02,
452       0u,
453       NULL
454     },
455     {
456       "Latin script. Some paragraphs.",
457       "Hello world\ndemo\n",
458       0u,
459       17u,
460       17u,
461       glyphs03,
462       characterIndices03,
463       charactersPerGlyph03,
464       2u,
465       newParagraphGlyphs03
466     },
467     {
468       "Malayalam script. More glyphs than characters.",
469       "ജോസോഹോവോ",
470       0u,
471       8u,
472       12u,
473       glyphs04,
474       characterIndices04,
475       charactersPerGlyph04,
476       0u,
477       NULL
478     },
479     {
480       "Latin script with some paragraphs. Update initial paragraph.",
481       "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
482       0u,
483       27u,
484       74u,
485       glyphs05,
486       characterIndices05,
487       charactersPerGlyph05,
488       1u,
489       newParagraphGlyphs05
490     },
491     {
492       "Latin script with some paragraphs. Update mid paragraph.",
493       "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
494       27u,
495       24u,
496       74u,
497       glyphs05,
498       characterIndices05,
499       charactersPerGlyph05,
500       1u,
501       newParagraphGlyphs06
502     },
503     {
504       "Latin script with some paragraphs. Update final paragraph.",
505       "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
506       51u,
507       24u,
508       74u,
509       glyphs05,
510       characterIndices05,
511       charactersPerGlyph05,
512       1u,
513       newParagraphGlyphs07
514     },
515   };
516   const unsigned int numberOfTests = 7u;
517
518   for( unsigned int index = 0u; index < numberOfTests; ++index )
519   {
520     if( !ShapeInfoTest( data[index] ) )
521     {
522       tet_result(TET_FAIL);
523     }
524   }
525
526   tet_result(TET_PASS);
527   END_TEST;
528 }