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