[dali_1.1.28] 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) 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   const Vector<FontDescriptionRun> fontDescriptions;
121   const LayoutOptions options;
122   CreateTextModel( data.text,
123                    textArea,
124                    fontDescriptions,
125                    options,
126                    layoutSize,
127                    logicalModel,
128                    visualModel );
129
130   // 2) Clear the model.
131
132   Vector<GlyphInfo>& glyphs = visualModel->mGlyphs;
133   Vector<CharacterIndex>& glyphToCharacter = visualModel->mGlyphsToCharacters;
134   Vector<Length>& charactersPerGlyph = visualModel->mCharactersPerGlyph;
135   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
136   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
137
138   // Get the glyph index.
139   GlyphIndex glyphIndex = 0u;
140   if( 0u != visualModel->mCharactersToGlyph.Count() )
141   {
142     glyphIndex = *( visualModel->mCharactersToGlyph.Begin() + data.index );
143
144     const CharacterIndex lastCharacterIndex = data.index + data.numberOfCharacters - 1u;
145     const Length numberOfGlyphs = *( visualModel->mCharactersToGlyph.Begin() + lastCharacterIndex ) + *( visualModel->mGlyphsPerCharacter.Begin() + lastCharacterIndex ) - glyphIndex;
146
147     // Erase the glyph info from the text model.
148     // Got from the ShapeText() function.
149     glyphs.Erase( glyphs.Begin() + glyphIndex, glyphs.Begin() + glyphIndex + numberOfGlyphs );
150     glyphToCharacter.Erase( glyphToCharacter.Begin() + glyphIndex, glyphToCharacter.Begin() + glyphIndex + numberOfGlyphs );
151     charactersPerGlyph.Erase( charactersPerGlyph.Begin() + glyphIndex, charactersPerGlyph.Begin() + glyphIndex + numberOfGlyphs );
152
153     // Got from the VisualModel::CreateCharacterToGlyphTable() and the VisualModel::CreateGlyphsPerCharacterTable() methods.
154     charactersToGlyph.Erase( charactersToGlyph.Begin() + data.index,
155                              charactersToGlyph.Begin() + data.index + data.numberOfCharacters );
156     glyphsPerCharacter.Erase( glyphsPerCharacter.Begin() + data.index,
157                               glyphsPerCharacter.Begin() + data.index + data.numberOfCharacters );
158
159     // Update the glyph to character indices.
160     for( Vector<CharacterIndex>::Iterator it = glyphToCharacter.Begin() + glyphIndex,
161            endIt = glyphToCharacter.End();
162          it != endIt;
163          ++it )
164     {
165       CharacterIndex& index = *it;
166       index -= data.numberOfCharacters;
167     }
168
169   }
170
171   // Reset the metrics got from the model as the ShapeText() function doesn't retrieve them.
172   for( Vector<GlyphInfo>::Iterator it = glyphs.Begin(),
173          endIt = glyphs.End();
174        it != endIt;
175        ++it )
176   {
177     GlyphInfo& info = *it;
178     info.width = 0.f;
179     info.height = 0.f;
180     info.xBearing = 0.f;
181     info.yBearing = 0.f;
182     info.scaleFactor = 0.f;
183   }
184
185   // 3) Call the ShapeText() function.
186
187   Vector<GlyphIndex> newParagraphGlyphs;
188
189   ShapeText( logicalModel->mText,
190              logicalModel->mLineBreakInfo,
191              logicalModel->mScriptRuns,
192              logicalModel->mFontRuns,
193              data.index,
194              glyphIndex,
195              data.numberOfCharacters,
196              glyphs,
197              glyphToCharacter,
198              charactersPerGlyph,
199              newParagraphGlyphs );
200
201   // Clear the advance of the new paragraph glyphs.
202   for( Vector<GlyphIndex>::Iterator it = newParagraphGlyphs.Begin(),
203          endIt = newParagraphGlyphs.End();
204        it != endIt;
205        ++it )
206   {
207     GlyphInfo& info = *( glyphs.Begin() + *it );
208     info.advance = 0.f;
209   }
210
211   // 4) Compare the results.
212
213   if( data.expectedNumberOfGlyphs != glyphs.Count() )
214   {
215     std::cout << "  Different number of glyphs : " << glyphs.Count() << ", expected : " << data.expectedNumberOfGlyphs << std::endl;
216     return false;
217   }
218
219   for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
220   {
221     if( !IsEqualGlyph( data.glyphs[index], glyphs[index] ) )
222     {
223       std::cout << "  different glyph info, index : " << index << std::endl;
224       return false;
225     }
226   }
227
228   for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
229   {
230     if( data.characterIndices[index] != glyphToCharacter[index] )
231     {
232       std::cout << "  different character index, index : " << index << std::endl;
233       return false;
234     }
235   }
236
237   for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
238   {
239     if( data.charactersPerGlyph[index] != charactersPerGlyph[index] )
240     {
241       std::cout << "  different character per glyph, index : " << index << std::endl;
242       return false;
243     }
244   }
245
246   if( data.expectedNumberOfNewParagraphGlyphs != newParagraphGlyphs.Count() )
247   {
248     std::cout << "  Different number of new paragraph glyphs : " << newParagraphGlyphs.Count() << ", expected : " << data.expectedNumberOfNewParagraphGlyphs << std::endl;
249     return false;
250   }
251
252   for( unsigned int index = 0u; index < data.expectedNumberOfNewParagraphGlyphs; ++index )
253   {
254     if( data.newParagraphGlyphs[index] != newParagraphGlyphs[index] )
255     {
256       std::cout << "  different new paragraph glyph, index : " << index << std::endl;
257       return false;
258     }
259   }
260
261   return true;
262 }
263
264 } // namespace
265
266 //////////////////////////////////////////////////////////
267
268 int UtcDaliTextShape(void)
269 {
270   ToolkitTestApplication application;
271   tet_infoline(" UtcDaliTextShape");
272
273   struct GlyphInfoData glyphs02[] =
274   {
275     { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
276     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
277     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
278     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
279     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
280     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
281     { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
282     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
283     { 1u, 85u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
284     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
285     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
286   };
287
288   CharacterIndex characterIndices02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
289   Length charactersPerGlyph02[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
290
291   struct GlyphInfoData glyphs03[] =
292   {
293     { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
294     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
295     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
296     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
297     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
298     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
299     { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
300     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
301     { 1u, 85u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
302     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
303     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
304     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
305     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
306     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
307     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
308     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
309     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
310   };
311
312   CharacterIndex characterIndices03[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u };
313   Length charactersPerGlyph03[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
314   CharacterIndex newParagraphGlyphs03[] = { 11u, 16u };
315
316   struct GlyphInfoData glyphs04[] =
317   {
318     { 2u, 160u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
319     { 2u, 123u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
320     { 2u, 153u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
321     { 2u, 160u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
322     { 2u, 150u, 0.f, 0.f, 0.f, 0.f, 14.f, 0.f },
323     { 2u, 153u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
324     { 2u, 160u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
325     { 2u, 151u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
326     { 2u, 153u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
327     { 2u, 160u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
328     { 2u, 147u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
329     { 2u, 153u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
330   };
331
332   CharacterIndex characterIndices04[] = { 0u, 0u, 0u, 2u, 2u, 2u, 4u, 4u, 4u, 6u, 6u, 6u };
333   Length charactersPerGlyph04[] = { 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u };
334
335   struct GlyphInfoData glyphs05[] =
336   {
337     { 1u, 47u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
338     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
339     { 1u, 85u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
340     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
341     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
342     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
343     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
344     { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
345     { 1u, 86u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
346     { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
347     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
348     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
349     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
350     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
351     { 1u, 79u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
352     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
353     { 1u, 85u, 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, 86u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
356     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
357     { 1u, 87u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
358     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
359     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
360     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
361     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
362     { 1u, 87u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
363     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
364     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
365     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
366     { 1u, 84u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
367     { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
368     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
369     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
370     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
371     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
372     { 1u, 5034u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
373     { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
374     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
375     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
376     { 1u, 69u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
377     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
378     { 1u, 86u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
379     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
380     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
381     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
382     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
383     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
384     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
385     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
386     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
387     { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
388     { 1u, 82u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
389     { 1u, 86u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
390     { 1u, 86u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
391     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
392     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
393     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
394     { 1u, 85u, 0.f, 0.f, 0.f, 0.f,  6.f, 0.f },
395     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
396     { 1u, 70u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
397     { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
398     { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
399     { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
400     { 1u, 76u, 0.f, 0.f, 0.f, 0.f,  4.f, 0.f },
401     { 1u, 68u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
402     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
403     { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
404     { 1u, 72u, 0.f, 0.f, 0.f, 0.f,  9.f, 0.f },
405     { 1u,  3u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
406     { 1u, 70u, 0.f, 0.f, 0.f, 0.f,  8.f, 0.f },
407     { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
408     { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
409     { 1u, 17u, 0.f, 0.f, 0.f, 0.f,  5.f, 0.f },
410     { 1u,  0u, 0.f, 0.f, 0.f, 0.f,  0.f, 0.f },
411   };
412
413   CharacterIndex characterIndices05[] = {  0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u,
414                                           10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u,
415                                           20u, 21u, 22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u,
416                                           30u, 31u, 32u, 33u, 34u, 35u, 37u, 38u, 39u, 40u,
417                                           41u, 42u, 43u, 44u, 45u, 46u, 47u, 48u, 49u, 50u,
418                                           51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u,
419                                           61u, 62u, 63u, 64u, 65u, 66u, 67u, 68u, 69u, 70u,
420                                           71u, 72u, 73u, 74u };
421   Length charactersPerGlyph05[] = { 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, 1u, 2u, 1u, 1u, 1u, 1u,
425                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
426                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
427                                     1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
428                                     1u, 1u, 1u, 1u };
429   CharacterIndex newParagraphGlyphs05[] = { 26u };
430   CharacterIndex newParagraphGlyphs06[] = { 49u };
431   CharacterIndex newParagraphGlyphs07[] = { 73u };
432
433   struct ShapeInfoData data[] =
434   {
435     {
436       "Zero characters",
437       "",
438       0u,
439       0u,
440       0u,
441       NULL,
442       NULL,
443       NULL,
444       0u,
445       NULL
446     },
447     {
448       "Latin script",
449       "Hello world",
450       0u,
451       11u,
452       11u,
453       glyphs02,
454       characterIndices02,
455       charactersPerGlyph02,
456       0u,
457       NULL
458     },
459     {
460       "Latin script. Some paragraphs.",
461       "Hello world\ndemo\n",
462       0u,
463       17u,
464       17u,
465       glyphs03,
466       characterIndices03,
467       charactersPerGlyph03,
468       2u,
469       newParagraphGlyphs03
470     },
471     {
472       "Malayalam script. More glyphs than characters.",
473       "ജോസോഹോവോ",
474       0u,
475       8u,
476       12u,
477       glyphs04,
478       characterIndices04,
479       charactersPerGlyph04,
480       0u,
481       NULL
482     },
483     {
484       "Latin script with some paragraphs. Update initial paragraph.",
485       "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
486       0u,
487       27u,
488       74u,
489       glyphs05,
490       characterIndices05,
491       charactersPerGlyph05,
492       1u,
493       newParagraphGlyphs05
494     },
495     {
496       "Latin script with some paragraphs. Update mid paragraph.",
497       "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
498       27u,
499       24u,
500       74u,
501       glyphs05,
502       characterIndices05,
503       charactersPerGlyph05,
504       1u,
505       newParagraphGlyphs06
506     },
507     {
508       "Latin script with some paragraphs. Update final paragraph.",
509       "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
510       51u,
511       24u,
512       74u,
513       glyphs05,
514       characterIndices05,
515       charactersPerGlyph05,
516       1u,
517       newParagraphGlyphs07
518     },
519   };
520   const unsigned int numberOfTests = 7u;
521
522   for( unsigned int index = 0u; index < numberOfTests; ++index )
523   {
524     if( !ShapeInfoTest( data[index] ) )
525     {
526       tet_result(TET_FAIL);
527     }
528   }
529
530   tet_result(TET_PASS);
531   END_TEST;
532 }