Fix text AutoScroll ellipsis issue
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / utc-Dali-Text-CharacterSpacing.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/layouts/layout-engine.h>
25 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
26 #include <dali-toolkit/internal/text/text-run-container.h>
27 #include <toolkit-text-utils.h>
28
29 using namespace Dali;
30 using namespace Toolkit;
31 using namespace Text;
32
33 // Tests the LayoutEngine methods.
34
35 //////////////////////////////////////////////////////////
36
37 namespace
38 {
39 const std::string DEFAULT_FONT_DIR("/resources/fonts");
40
41 struct LayoutTextData
42 {
43   std::string          description;
44   std::string          text;
45   Size                 textArea;
46   unsigned int         numberOfFonts;
47   FontDescriptionRun*  fontDescriptions;
48   Size                 layoutSize;
49   unsigned int         totalNumberOfGlyphs;
50   float*               positions;
51   unsigned int         numberOfLines;
52   LineRun*             lines;
53   Layout::Engine::Type layout;
54   unsigned int         startIndex;
55   unsigned int         numberOfGlyphs;
56   bool                 ellipsis : 1;
57   bool                 updated : 1;
58   float                characterSpacing;
59 };
60
61 void Print(const LineRun& line)
62 {
63   std::cout << "        glyph run, index : " << line.glyphRun.glyphIndex << ", num glyphs : " << line.glyphRun.numberOfGlyphs << std::endl;
64   std::cout << "    character run, index : " << line.characterRun.characterIndex << ", num chars : " << line.characterRun.numberOfCharacters << std::endl;
65   std::cout << "                   width : " << floor(line.width) << std::endl;
66   std::cout << "                ascender : " << line.ascender << std::endl;
67   std::cout << "               descender : " << line.descender << std::endl;
68   std::cout << "             extraLength : " << line.extraLength << std::endl;
69   std::cout << "         alignmentOffset : " << line.alignmentOffset << std::endl;
70   std::cout << "               direction : " << line.direction << std::endl;
71   std::cout << "                ellipsis : " << line.ellipsis << std::endl;
72 }
73
74 bool LayoutTextTest(const LayoutTextData& data)
75 {
76   // Load some fonts.
77   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
78   fontClient.SetDpi(96u, 96u);
79
80   char*             pathNamePtr = get_current_dir_name();
81   const std::string pathName(pathNamePtr);
82   free(pathNamePtr);
83
84   fontClient.GetFontId(pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf");
85   fontClient.GetFontId(pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf");
86   fontClient.GetFontId(pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf");
87   fontClient.GetFontId(pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHindiRegular.ttf");
88
89   // 1) Create the model.
90   ModelPtr   textModel;
91   MetricsPtr metrics;
92   Size       layoutSize;
93
94   Vector<FontDescriptionRun> fontDescriptionRuns;
95   if(0u != data.numberOfFonts)
96   {
97     fontDescriptionRuns.Insert(fontDescriptionRuns.End(),
98                                data.fontDescriptions,
99                                data.fontDescriptions + data.numberOfFonts);
100   }
101
102   LayoutOptions options;
103   options.align = false;
104   CreateTextModel(data.text,
105                   data.textArea,
106                   fontDescriptionRuns,
107                   options,
108                   layoutSize,
109                   textModel,
110                   metrics,
111                   false,
112                   LineWrap::WORD,
113                   false,
114                   Toolkit::DevelText::EllipsisPosition::END,
115                   0.0f, // lineSpacing
116                   data.characterSpacing);
117
118   LogicalModelPtr logicalModel = textModel->mLogicalModel;
119   VisualModelPtr  visualModel  = textModel->mVisualModel;
120
121   // 2) Clear the layout.
122   Vector<LineRun>& lines = visualModel->mLines;
123
124   const Length     numberOfCharacters = logicalModel->mText.Count();
125   const bool       isLastNewParagraph = (0u == numberOfCharacters) ? false : TextAbstraction::IsNewParagraph(*(logicalModel->mText.Begin() + (numberOfCharacters - 1u)));
126   const GlyphIndex lastGlyphIndex     = data.startIndex + data.numberOfGlyphs - 1u;
127   const bool       removeLastLine     = isLastNewParagraph && (lastGlyphIndex + 1u == visualModel->mGlyphs.Count());
128
129   LineIndex startRemoveIndex = 0u;
130
131   if(0u != lines.Count())
132   {
133     startRemoveIndex         = lines.Count();
134     LineIndex endRemoveIndex = startRemoveIndex;
135     ClearGlyphRuns(data.startIndex,
136                    lastGlyphIndex + (removeLastLine ? 1u : 0u),
137                    lines,
138                    startRemoveIndex,
139                    endRemoveIndex);
140
141     // Update the character runs of the lines.
142     const CharacterIndex* const glyphsToCharactersBuffer = visualModel->mGlyphsToCharacters.Begin();
143     const Length* const         charactersPerGlyph       = visualModel->mCharactersPerGlyph.Begin();
144     const CharacterIndex        startCharacterIndex      = *(glyphsToCharactersBuffer + data.startIndex);
145     const CharacterIndex        lastCharacterIndex       = *(glyphsToCharactersBuffer + lastGlyphIndex) + *(charactersPerGlyph + lastGlyphIndex) - 1u;
146     ClearCharacterRuns(startCharacterIndex,
147                        lastCharacterIndex + (removeLastLine ? 1u : 0u),
148                        lines,
149                        startRemoveIndex,
150                        endRemoveIndex);
151
152     lines.Erase(lines.Begin() + startRemoveIndex,
153                 lines.Begin() + endRemoveIndex);
154   }
155
156   Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
157
158   glyphPositions.Erase(glyphPositions.Begin() + data.startIndex,
159                        glyphPositions.Begin() + data.startIndex + data.numberOfGlyphs);
160
161   // 3) Layout
162   Layout::Engine engine;
163   engine.SetMetrics(metrics);
164   engine.SetLayout(data.layout);
165
166   textModel->mHorizontalAlignment   = Text::HorizontalAlignment::BEGIN;
167   textModel->mLineWrapMode          = LineWrap::WORD;
168   textModel->mIgnoreSpacesAfterText = true;
169   //textModel->mMatchSystemLanguageDirection = false;
170   Layout::Parameters layoutParameters(data.textArea,
171                                       textModel);
172
173   layoutParameters.isLastNewParagraph = isLastNewParagraph;
174
175   // The initial glyph and the number of glyphs to layout.
176   layoutParameters.startGlyphIndex        = data.startIndex;
177   layoutParameters.numberOfGlyphs         = data.numberOfGlyphs;
178   layoutParameters.startLineIndex         = startRemoveIndex;
179   layoutParameters.estimatedNumberOfLines = logicalModel->mParagraphInfo.Count();
180
181   layoutSize = Vector2::ZERO;
182
183   bool       isAutoScroll                   = false;
184   bool       isAutoScrollMaxTextureExceeded = false;
185   const bool updated                        = engine.LayoutText(layoutParameters,
186                                          layoutSize,
187                                          data.ellipsis,
188                                          isAutoScroll,
189                                          isAutoScrollMaxTextureExceeded,
190                                          DevelText::EllipsisPosition::END);
191
192   // 4) Compare the results.
193
194   if(updated != data.updated)
195   {
196     std::cout << "  Different updated bool : " << updated << ", expected : " << data.updated << std::endl;
197     return false;
198   }
199
200   if(layoutSize != data.layoutSize)
201   {
202     std::cout << "  Different layout size : " << layoutSize << ", expected : " << data.layoutSize << std::endl;
203     return false;
204   }
205
206   for(unsigned int index = 0u; index < data.totalNumberOfGlyphs; ++index)
207   {
208     const Vector2& position = *(glyphPositions.Begin() + index);
209
210     if(fabsf(std::round(position.x) - std::round(*(data.positions + 2u * index))) > Math::MACHINE_EPSILON_1000)
211     {
212       std::cout << "  Different position for glyph " << index << " x : " << position.x << ", expected : " << *(data.positions + 2u * index) << std::endl;
213       return false;
214     }
215     if(fabsf(position.y - *(data.positions + 2u * index + 1u)) > Math::MACHINE_EPSILON_1000)
216     {
217       std::cout << "  Different position for glyph " << index << " y : " << position.y << ", expected : " << *(data.positions + 2u * index + 1u) << std::endl;
218       return false;
219     }
220   }
221
222   if(lines.Count() != data.numberOfLines)
223   {
224     std::cout << "  Different number of lines : " << lines.Count() << ", expected : " << data.numberOfLines << std::endl;
225     return false;
226   }
227
228   for(unsigned int index = 0u; index < data.numberOfLines; ++index)
229   {
230     const LineRun& line         = *(lines.Begin() + index);
231     const LineRun& expectedLine = *(data.lines + index);
232
233     if(line.glyphRun.glyphIndex != expectedLine.glyphRun.glyphIndex)
234     {
235       std::cout << "  Different line info for line : " << index << std::endl;
236       Print(line);
237       std::cout << "  expected" << std::endl;
238       Print(expectedLine);
239       return false;
240     }
241     if(line.glyphRun.numberOfGlyphs != expectedLine.glyphRun.numberOfGlyphs)
242     {
243       std::cout << "  Different line info for line : " << index << std::endl;
244       Print(line);
245       std::cout << "  expected" << std::endl;
246       Print(expectedLine);
247       return false;
248     }
249
250     if(line.characterRun.characterIndex != expectedLine.characterRun.characterIndex)
251     {
252       std::cout << "  Different line info for line : " << index << std::endl;
253       Print(line);
254       std::cout << "  expected" << std::endl;
255       Print(expectedLine);
256       return false;
257     }
258     if(line.characterRun.numberOfCharacters != expectedLine.characterRun.numberOfCharacters)
259     {
260       std::cout << "  Different line info for line : " << index << std::endl;
261       Print(line);
262       std::cout << "  expected" << std::endl;
263       Print(expectedLine);
264       return false;
265     }
266
267     if(fabsf(floor(line.width) - expectedLine.width) > Math::MACHINE_EPSILON_1)
268     {
269       std::cout << "  Different line info for line : " << index << std::endl;
270       Print(line);
271       std::cout << "  expected" << std::endl;
272       Print(expectedLine);
273       return false;
274     }
275
276     if(fabsf(line.ascender - expectedLine.ascender) > Math::MACHINE_EPSILON_1)
277     {
278       std::cout << "  Different line info for line : " << index << std::endl;
279       Print(line);
280       std::cout << "  expected" << std::endl;
281       Print(expectedLine);
282       return false;
283     }
284
285     if(fabsf(line.descender - expectedLine.descender) > Math::MACHINE_EPSILON_1)
286     {
287       std::cout << "  Different line info for line : " << index << std::endl;
288       Print(line);
289       std::cout << "  expected" << std::endl;
290       Print(expectedLine);
291       return false;
292     }
293
294     if(fabsf(line.extraLength - expectedLine.extraLength) > Math::MACHINE_EPSILON_1)
295     {
296       std::cout << "  Different line info for line : " << index << std::endl;
297       Print(line);
298       std::cout << "  expected" << std::endl;
299       Print(expectedLine);
300       return false;
301     }
302
303     if(line.ellipsis != expectedLine.ellipsis)
304     {
305       std::cout << "  Different line info for line : " << index << std::endl;
306       Print(line);
307       std::cout << "  expected" << std::endl;
308       Print(expectedLine);
309       return false;
310     }
311
312     // Do not compare the alignment offset as it's not calculated in the layout.
313     // Do not compare the line direction as it's not set in the layout.
314   }
315
316   return true;
317 }
318
319 ////////////////////////////////////////////////////////
320
321 } // namespace
322
323 //////////////////////////////////////////////////////////
324 //
325 // UtcDaliTextCharacterSpacingSingleLineTextArea1
326 // UtcDaliTextCharacterSpacingSingleLineTextArea2
327 // UtcDaliTextCharacterSpacingSingleLineTextArea3
328 // UtcDaliTextCharacterSpacingMultilineText1
329 // UtcDaliTextCharacterSpacingMultilineText2
330 //
331 //////////////////////////////////////////////////////////
332
333 int UtcDaliTextCharacterSpacingSingleLineTextArea1(void)
334 {
335   ToolkitTestApplication application;
336   tet_infoline(" UtcDaliTextCharacterSpacingSingleLineTextArea1");
337
338   // Will layout the text in single line as it can be scrolled.
339
340   const std::string fontFamily("TizenSans");
341
342   // Set a known font description
343   FontDescriptionRun fontDescriptionRun;
344   fontDescriptionRun.characterRun.characterIndex     = 0u;
345   fontDescriptionRun.characterRun.numberOfCharacters = 11u;
346   fontDescriptionRun.familyLength                    = fontFamily.size();
347   fontDescriptionRun.familyName                      = new char[fontDescriptionRun.familyLength];
348   memcpy(fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength);
349   fontDescriptionRun.familyDefined = true;
350   fontDescriptionRun.weightDefined = false;
351   fontDescriptionRun.widthDefined  = false;
352   fontDescriptionRun.slantDefined  = false;
353   fontDescriptionRun.sizeDefined   = false;
354
355   Vector<FontDescriptionRun> fontDescriptionRuns;
356   fontDescriptionRuns.PushBack(fontDescriptionRun);
357   Size textArea(1.f, 1.f);
358
359   //******* characterSpacing = 0.0f *******//
360   float positions[] = {
361     0.f, -12.f, 10.f, -9.f, 19.875f, -13.f, 23.8906f, -13.f, 26.9062f, -9.f, 36.1875f, -0.f, 40.1875f, -9.f, 52.1562f, -9.f, 62.4375f, -9.f, 68.5f, -13.f, 71.5156f, -13.f};
362   Size layoutSize(81.f, 20.f);
363   //************************************//
364
365   struct LineRun line =
366     {
367       {0u, 11u},
368       {0u, 11u},
369       81.f,
370       15.f,
371       -5.f,
372       0.f,
373       0.f,
374       0.f,
375       false,
376       false};
377   Vector<LineRun> lines;
378   lines.PushBack(line);
379
380   LayoutTextData data =
381     {
382       "Layout text in a small area",
383       "Hello world",
384       textArea,
385       1u,
386       fontDescriptionRuns.Begin(),
387       layoutSize,
388       11u,
389       positions,
390       1u,
391       lines.Begin(),
392       Layout::Engine::SINGLE_LINE_BOX,
393       0u,
394       11u,
395       false,
396       true,
397       0.0f};
398
399   if(!LayoutTextTest(data))
400   {
401     tet_result(TET_FAIL);
402   }
403
404   tet_result(TET_PASS);
405   END_TEST;
406 }
407
408 int UtcDaliTextCharacterSpacingSingleLineTextArea2(void)
409 {
410   ToolkitTestApplication application;
411   tet_infoline(" UtcDaliTextCharacterSpacingSingleLineTextArea2");
412
413   // Will layout the text in single line as it can be scrolled.
414
415   const std::string fontFamily("TizenSans");
416
417   // Set a known font description
418   FontDescriptionRun fontDescriptionRun;
419   fontDescriptionRun.characterRun.characterIndex     = 0u;
420   fontDescriptionRun.characterRun.numberOfCharacters = 11u;
421   fontDescriptionRun.familyLength                    = fontFamily.size();
422   fontDescriptionRun.familyName                      = new char[fontDescriptionRun.familyLength];
423   memcpy(fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength);
424   fontDescriptionRun.familyDefined = true;
425   fontDescriptionRun.weightDefined = false;
426   fontDescriptionRun.widthDefined  = false;
427   fontDescriptionRun.slantDefined  = false;
428   fontDescriptionRun.sizeDefined   = false;
429
430   Vector<FontDescriptionRun> fontDescriptionRuns;
431   fontDescriptionRuns.PushBack(fontDescriptionRun);
432   Size textArea(1.f, 1.f);
433
434   //******* characterSpacing = 2.0f *******//
435   float positions[] = {
436     0.f, -12.f, 12.f, -9.f, 23.875f, -13.f, 29.8906f, -13.f, 34.9062f, -9.f, 46.1875f, -0.f, 52.1875f, -9.f, 66.1562f, -9.f, 78.4375f, -9.f, 86.5f, -13.f, 91.5156f, -13.f};
437   Size layoutSize(101.f, 20.f);
438   //************************************//
439
440   struct LineRun line =
441     {
442       {0u, 11u},
443       {0u, 11u},
444       101.f,
445       15.f,
446       -5.f,
447       0.f,
448       0.f,
449       0.f,
450       false,
451       false};
452   Vector<LineRun> lines;
453   lines.PushBack(line);
454
455   LayoutTextData data =
456     {
457       "Layout text in a small area",
458       "Hello world",
459       textArea,
460       1u,
461       fontDescriptionRuns.Begin(),
462       layoutSize,
463       11u,
464       positions,
465       1u,
466       lines.Begin(),
467       Layout::Engine::SINGLE_LINE_BOX,
468       0u,
469       11u,
470       false,
471       true,
472       2.0f};
473
474   if(!LayoutTextTest(data))
475   {
476     tet_result(TET_FAIL);
477   }
478
479   tet_result(TET_PASS);
480   END_TEST;
481 }
482
483 int UtcDaliTextCharacterSpacingSingleLineTextArea3(void)
484 {
485   ToolkitTestApplication application;
486   tet_infoline(" UtcDaliTextCharacterSpacingSingleLineTextArea3");
487
488   // Will layout the text in single line as it can be scrolled.
489
490   const std::string fontFamily("TizenSans");
491
492   // Set a known font description
493   FontDescriptionRun fontDescriptionRun;
494   fontDescriptionRun.characterRun.characterIndex     = 0u;
495   fontDescriptionRun.characterRun.numberOfCharacters = 11u;
496   fontDescriptionRun.familyLength                    = fontFamily.size();
497   fontDescriptionRun.familyName                      = new char[fontDescriptionRun.familyLength];
498   memcpy(fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength);
499   fontDescriptionRun.familyDefined = true;
500   fontDescriptionRun.weightDefined = false;
501   fontDescriptionRun.widthDefined  = false;
502   fontDescriptionRun.slantDefined  = false;
503   fontDescriptionRun.sizeDefined   = false;
504
505   Vector<FontDescriptionRun> fontDescriptionRuns;
506   fontDescriptionRuns.PushBack(fontDescriptionRun);
507   Size textArea(1.f, 1.f);
508
509   //******* characterSpacing = 4.0f *******//
510   float positions[] = {
511     0.f, -12.f, 14.f, -9.f, 27.875f, -13.f, 35.8906f, -13.f, 42.9062f, -9.f, 56.1875f, -0.f, 64.1875f, -9.f, 80.1562f, -9.f, 94.4375f, -9.f, 104.5f, -13.f, 111.5156f, -13.f};
512   Size layoutSize(121.f, 20.f);
513   //************************************//
514
515   struct LineRun line =
516     {
517       {0u, 11u},
518       {0u, 11u},
519       121.f,
520       15.f,
521       -5.f,
522       0.f,
523       0.f,
524       0.f,
525       false,
526       false};
527   Vector<LineRun> lines;
528   lines.PushBack(line);
529
530   LayoutTextData data =
531     {
532       "Layout text in a small area",
533       "Hello world",
534       textArea,
535       1u,
536       fontDescriptionRuns.Begin(),
537       layoutSize,
538       11u,
539       positions,
540       1u,
541       lines.Begin(),
542       Layout::Engine::SINGLE_LINE_BOX,
543       0u,
544       11u,
545       false,
546       true,
547       4.0f};
548
549   if(!LayoutTextTest(data))
550   {
551     tet_result(TET_FAIL);
552   }
553
554   tet_result(TET_PASS);
555   END_TEST;
556 }
557
558 int UtcDaliTextCharacterSpacingMultilineText1(void)
559 {
560   ToolkitTestApplication application;
561   tet_infoline(" UtcDaliTextCharacterSpacingMultilineText1");
562
563   // Layout some lines of left to right text.
564
565   const std::string fontFamily("TizenSans");
566
567   // Set a known font description
568   FontDescriptionRun fontDescriptionRun1;
569   fontDescriptionRun1.characterRun.characterIndex     = 0u;
570   fontDescriptionRun1.characterRun.numberOfCharacters = 18u;
571   fontDescriptionRun1.familyLength                    = fontFamily.size();
572   fontDescriptionRun1.familyName                      = new char[fontDescriptionRun1.familyLength];
573   memcpy(fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength);
574   fontDescriptionRun1.familyDefined = true;
575   fontDescriptionRun1.weightDefined = false;
576   fontDescriptionRun1.widthDefined  = false;
577   fontDescriptionRun1.slantDefined  = false;
578   fontDescriptionRun1.sizeDefined   = false;
579
580   FontDescriptionRun fontDescriptionRun2;
581   fontDescriptionRun2.characterRun.characterIndex     = 18u;
582   fontDescriptionRun2.characterRun.numberOfCharacters = 31u;
583   fontDescriptionRun2.familyLength                    = fontFamily.size();
584   fontDescriptionRun2.familyName                      = new char[fontDescriptionRun2.familyLength];
585   memcpy(fontDescriptionRun2.familyName, fontFamily.c_str(), fontDescriptionRun2.familyLength);
586   fontDescriptionRun2.familyDefined = true;
587   fontDescriptionRun2.weightDefined = false;
588   fontDescriptionRun2.widthDefined  = false;
589   fontDescriptionRun2.slantDefined  = false;
590   fontDescriptionRun2.sizeDefined   = false;
591
592   Vector<FontDescriptionRun> fontDescriptionRuns;
593   fontDescriptionRuns.PushBack(fontDescriptionRun1);
594   fontDescriptionRuns.PushBack(fontDescriptionRun2);
595   Size  textArea(100.f, 300.f);
596   Size  layoutSize(98.f, 97.f);
597   float positions[] =
598     {
599       0.f, -12.f, 10.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 52.f, -9.f, 62.f, -9.f, 69.f, -13.f, 72.f, -13.f, 81.f, -0.f, 0.f, -13.f, 9.f, -9.f, 19.f, -9.f, 32.f, -9.f, 41.f, -2.f, 45.f, -12.f, 0.f, -12.f, 7.92188f, -9.f, 18.f, -9.f, 27.2031f, -9.f, 38.f, -9.f, 47.f, -11.f, 53.f, -0.f, 0.f, -12.f, 11.1562f, -12.f, 15.f, -12.f, 26.f, -9.f, 36.4844f, -9.f, 42.f, -9.f, 52.5469f, -9.f, 61.6875f, -11.f, 67.9688f, -0.f, 0.f, -12.f, 4.f, -12.f, 9.f, -9.f, 18.0469f, -9.f, 27.8906f, -9.f, 36.f, -0.f, 41.3281f, -9.f, 51.125f, -12.f, 57.f, -0.f, 62.f, -11.f, 68.1406f, -9.f, 77.7031f, -9.f, 87.f, -11.f, 94.4531f, -2.f};
600   struct LineRun line0 =
601     {
602       {0u, 12u},
603       {0u, 12u},
604       81.f,
605       15.f,
606       -5.f,
607       4.f,
608       0.f,
609       0.f,
610       false,
611       false};
612   struct LineRun line1 =
613     {
614       {12u, 6u},
615       {12u, 6u},
616       44.f,
617       15.f,
618       -5.f,
619       0.f,
620       0.f,
621       0.f,
622       false,
623       false};
624   struct LineRun line2 =
625     {
626       {18u, 7u},
627       {18u, 7u},
628       54.f,
629       15.f,
630       -4.f,
631       6.f,
632       0.f,
633       0.f,
634       false,
635       false};
636   struct LineRun line3 =
637     {
638       {25u, 9u},
639       {25u, 10u},
640       68.f,
641       15.f,
642       -4.f,
643       6.f,
644       0.f,
645       0.f,
646       false,
647       false};
648   struct LineRun line4 =
649     {
650       {34u, 14u},
651       {35u, 14u},
652       98.f,
653       15.f,
654       -4.f,
655       0.f,
656       0.f,
657       0.f,
658       false,
659       false};
660   Vector<LineRun> lines;
661   lines.PushBack(line0);
662   lines.PushBack(line1);
663   lines.PushBack(line2);
664   lines.PushBack(line3);
665   lines.PushBack(line4);
666
667   LayoutTextData data =
668     {
669       "Layout simple multiline text",
670       "Hello world demo.\n"
671       "Layout different lines of text.",
672       textArea,
673       1u,
674       fontDescriptionRuns.Begin(),
675       layoutSize,
676       48u,
677       positions,
678       5u,
679       lines.Begin(),
680       Layout::Engine::MULTI_LINE_BOX,
681       0u,
682       48u,
683       false,
684       true,
685       0.0f};
686
687   if(!LayoutTextTest(data))
688   {
689     tet_result(TET_FAIL);
690   }
691
692   tet_result(TET_PASS);
693   END_TEST;
694 }
695
696 int UtcDaliTextCharacterSpacingMultilineText2(void)
697 {
698   ToolkitTestApplication application;
699   tet_infoline(" UtcDaliTextCharacterSpacingMultilineText2");
700
701   // Layout some lines of left to right text.
702
703   const std::string fontFamily("TizenSans");
704
705   // Set a known font description
706   FontDescriptionRun fontDescriptionRun1;
707   fontDescriptionRun1.characterRun.characterIndex     = 0u;
708   fontDescriptionRun1.characterRun.numberOfCharacters = 18u;
709   fontDescriptionRun1.familyLength                    = fontFamily.size();
710   fontDescriptionRun1.familyName                      = new char[fontDescriptionRun1.familyLength];
711   memcpy(fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength);
712   fontDescriptionRun1.familyDefined = true;
713   fontDescriptionRun1.weightDefined = false;
714   fontDescriptionRun1.widthDefined  = false;
715   fontDescriptionRun1.slantDefined  = false;
716   fontDescriptionRun1.sizeDefined   = false;
717
718   FontDescriptionRun fontDescriptionRun2;
719   fontDescriptionRun2.characterRun.characterIndex     = 18u;
720   fontDescriptionRun2.characterRun.numberOfCharacters = 31u;
721   fontDescriptionRun2.familyLength                    = fontFamily.size();
722   fontDescriptionRun2.familyName                      = new char[fontDescriptionRun2.familyLength];
723   memcpy(fontDescriptionRun2.familyName, fontFamily.c_str(), fontDescriptionRun2.familyLength);
724   fontDescriptionRun2.familyDefined = true;
725   fontDescriptionRun2.weightDefined = false;
726   fontDescriptionRun2.widthDefined  = false;
727   fontDescriptionRun2.slantDefined  = false;
728   fontDescriptionRun2.sizeDefined   = false;
729
730   Vector<FontDescriptionRun> fontDescriptionRuns;
731   fontDescriptionRuns.PushBack(fontDescriptionRun1);
732   fontDescriptionRuns.PushBack(fontDescriptionRun2);
733   Size  textArea(100.f, 300.f);
734   Size  layoutSize(82.f, 136.f);
735   float positions[] =
736     {
737       0.f, -12.f, 12.f, -9.f, 24.f, -13.f, 30.f, -13.f, 35.f, -9.f, 46.f, -0.f, 0.f, -9.f, 13.9688f, -9.f, 26.25f, -9.f, 34.3125f, -13.f, 39.3281f, -13.f, 50.6406f, -0.f, 0.f, -13.f, 11.3125f, -9.f, 22.7031f, -9.f, 37.5625, -9.f, 48.8438f, -2.f, 54.8125, -12.f, 0.f, -12.f, 9.92188f, -9.f, 21.7344, -9.f, 33.2031f, -9.f, 46.f, -9.f, 57.1406f, -11.f, 65.4219f, -0.f, 0.f, -12.f, 13.1562f, -12.f, 18.6094f, -12.f, 31.6406f, -9.f, 44.4844f, -9.f, 51.7031f, -9.f, 64.5469f, -9.f, 75.6875f, -11.f, 83.9688, -0.f, 0.f, -12.f, 6.45312f, -12.f, 12.9062f, -9.f, 24.0469f, -9.f, 35.8906f, -9.f, 46.2344f, -0.f, 53.3281f, -9.f, 65.125f, -12.f, 72.7656f, -0.f, 0.f, -11.f, 8.28125f, -9.f, 19.8438f, -9.f, 31.3125f, -11.f, 40.5938f, -2.f};
738   struct LineRun line0 =
739     {
740       {0u, 6u},
741       {0u, 6u},
742       44.f,
743       15.f,
744       -5.f,
745       6.f,
746       0.f,
747       0.f,
748       false,
749       false};
750   struct LineRun line1 =
751     {
752       {6u, 6u},
753       {6u, 6u},
754       49.f,
755       15.f,
756       -5.f,
757       6.f,
758       0.f,
759       0.f,
760       false,
761       false};
762   struct LineRun line2 =
763     {
764       {12u, 6u},
765       {12u, 6u},
766       52.f,
767       15.f,
768       -5.f,
769       0.f,
770       0.f,
771       0.f,
772       false,
773       false};
774   struct LineRun line3 =
775     {
776       {18u, 7u},
777       {18u, 7u},
778       64.f,
779       15.f,
780       -4.f,
781       8.f,
782       0.f,
783       0.f,
784       false,
785       false};
786   struct LineRun line4 =
787     {
788       {25u, 9u},
789       {25u, 10u},
790       82.f,
791       15.f,
792       -4.f,
793       8.f,
794       0.f,
795       0.f,
796       false,
797       false};
798   struct LineRun line5 =
799     {
800       {34u, 9u},
801       {35u, 9u},
802       72.f,
803       15.f,
804       -4.f,
805       8.f,
806       0.f,
807       0.f,
808       false,
809       false};
810   struct LineRun line6 =
811     {
812       {43u, 5u},
813       {44u, 5u},
814       44.f,
815       15.f,
816       -4.f,
817       0.f,
818       0.f,
819       0.f,
820       false,
821       false};
822   Vector<LineRun> lines;
823   lines.PushBack(line0);
824   lines.PushBack(line1);
825   lines.PushBack(line2);
826   lines.PushBack(line3);
827   lines.PushBack(line4);
828   lines.PushBack(line5);
829   lines.PushBack(line6);
830
831   LayoutTextData data =
832     {
833       "Layout simple multiline text",
834       "Hello world demo.\n"
835       "Layout different lines of text.",
836       textArea,
837       1u,
838       fontDescriptionRuns.Begin(),
839       layoutSize,
840       48u,
841       positions,
842       7u,
843       lines.Begin(),
844       Layout::Engine::MULTI_LINE_BOX,
845       0u,
846       48u,
847       false,
848       true,
849       2.0f};
850
851   if(!LayoutTextTest(data))
852   {
853     tet_result(TET_FAIL);
854   }
855
856   tet_result(TET_PASS);
857   END_TEST;
858 }