[dali_2.3.21] Merge branch 'devel/master'
[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   bool       isHiddenInputEnabled           = false;
186   const bool updated                        = engine.LayoutText(layoutParameters,
187                                          layoutSize,
188                                          data.ellipsis,
189                                          isAutoScroll,
190                                          isAutoScrollMaxTextureExceeded,
191                                          isHiddenInputEnabled,
192                                          DevelText::EllipsisPosition::END);
193
194   // 4) Compare the results.
195
196   if(updated != data.updated)
197   {
198     std::cout << "  Different updated bool : " << updated << ", expected : " << data.updated << std::endl;
199     return false;
200   }
201
202   if(layoutSize != data.layoutSize)
203   {
204     std::cout << "  Different layout size : " << layoutSize << ", expected : " << data.layoutSize << std::endl;
205     return false;
206   }
207
208   for(unsigned int index = 0u; index < data.totalNumberOfGlyphs; ++index)
209   {
210     const Vector2& position = *(glyphPositions.Begin() + index);
211
212     if(fabsf(std::round(position.x) - std::round(*(data.positions + 2u * index))) > Math::MACHINE_EPSILON_1000)
213     {
214       std::cout << "  Different position for glyph " << index << " x : " << position.x << ", expected : " << *(data.positions + 2u * index) << std::endl;
215       return false;
216     }
217     if(fabsf(position.y - *(data.positions + 2u * index + 1u)) > Math::MACHINE_EPSILON_1000)
218     {
219       std::cout << "  Different position for glyph " << index << " y : " << position.y << ", expected : " << *(data.positions + 2u * index + 1u) << std::endl;
220       return false;
221     }
222   }
223
224   if(lines.Count() != data.numberOfLines)
225   {
226     std::cout << "  Different number of lines : " << lines.Count() << ", expected : " << data.numberOfLines << std::endl;
227     return false;
228   }
229
230   for(unsigned int index = 0u; index < data.numberOfLines; ++index)
231   {
232     const LineRun& line         = *(lines.Begin() + index);
233     const LineRun& expectedLine = *(data.lines + index);
234
235     if(line.glyphRun.glyphIndex != expectedLine.glyphRun.glyphIndex)
236     {
237       std::cout << "  Different line info for line : " << index << std::endl;
238       Print(line);
239       std::cout << "  expected" << std::endl;
240       Print(expectedLine);
241       return false;
242     }
243     if(line.glyphRun.numberOfGlyphs != expectedLine.glyphRun.numberOfGlyphs)
244     {
245       std::cout << "  Different line info for line : " << index << std::endl;
246       Print(line);
247       std::cout << "  expected" << std::endl;
248       Print(expectedLine);
249       return false;
250     }
251
252     if(line.characterRun.characterIndex != expectedLine.characterRun.characterIndex)
253     {
254       std::cout << "  Different line info for line : " << index << std::endl;
255       Print(line);
256       std::cout << "  expected" << std::endl;
257       Print(expectedLine);
258       return false;
259     }
260     if(line.characterRun.numberOfCharacters != expectedLine.characterRun.numberOfCharacters)
261     {
262       std::cout << "  Different line info for line : " << index << std::endl;
263       Print(line);
264       std::cout << "  expected" << std::endl;
265       Print(expectedLine);
266       return false;
267     }
268
269     if(fabsf(floor(line.width) - expectedLine.width) > Math::MACHINE_EPSILON_1)
270     {
271       std::cout << "  Different line info for line : " << index << std::endl;
272       Print(line);
273       std::cout << "  expected" << std::endl;
274       Print(expectedLine);
275       return false;
276     }
277
278     if(fabsf(line.ascender - expectedLine.ascender) > Math::MACHINE_EPSILON_1)
279     {
280       std::cout << "  Different line info for line : " << index << std::endl;
281       Print(line);
282       std::cout << "  expected" << std::endl;
283       Print(expectedLine);
284       return false;
285     }
286
287     if(fabsf(line.descender - expectedLine.descender) > Math::MACHINE_EPSILON_1)
288     {
289       std::cout << "  Different line info for line : " << index << std::endl;
290       Print(line);
291       std::cout << "  expected" << std::endl;
292       Print(expectedLine);
293       return false;
294     }
295
296     if(fabsf(line.extraLength - expectedLine.extraLength) > Math::MACHINE_EPSILON_1)
297     {
298       std::cout << "  Different line info for line : " << index << std::endl;
299       Print(line);
300       std::cout << "  expected" << std::endl;
301       Print(expectedLine);
302       return false;
303     }
304
305     if(line.ellipsis != expectedLine.ellipsis)
306     {
307       std::cout << "  Different line info for line : " << index << std::endl;
308       Print(line);
309       std::cout << "  expected" << std::endl;
310       Print(expectedLine);
311       return false;
312     }
313
314     // Do not compare the alignment offset as it's not calculated in the layout.
315     // Do not compare the line direction as it's not set in the layout.
316   }
317
318   return true;
319 }
320
321 ////////////////////////////////////////////////////////
322
323 } // namespace
324
325 //////////////////////////////////////////////////////////
326 //
327 // UtcDaliTextCharacterSpacingSingleLineTextArea1
328 // UtcDaliTextCharacterSpacingSingleLineTextArea2
329 // UtcDaliTextCharacterSpacingSingleLineTextArea3
330 // UtcDaliTextCharacterSpacingMultilineText1
331 // UtcDaliTextCharacterSpacingMultilineText2
332 //
333 //////////////////////////////////////////////////////////
334
335 int UtcDaliTextCharacterSpacingSingleLineTextArea1(void)
336 {
337   ToolkitTestApplication application;
338   tet_infoline(" UtcDaliTextCharacterSpacingSingleLineTextArea1");
339
340   // Will layout the text in single line as it can be scrolled.
341
342   const std::string fontFamily("TizenSans");
343
344   // Set a known font description
345   FontDescriptionRun fontDescriptionRun;
346   fontDescriptionRun.characterRun.characterIndex     = 0u;
347   fontDescriptionRun.characterRun.numberOfCharacters = 11u;
348   fontDescriptionRun.familyLength                    = fontFamily.size();
349   fontDescriptionRun.familyName                      = new char[fontDescriptionRun.familyLength];
350   memcpy(fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength);
351   fontDescriptionRun.familyDefined = true;
352   fontDescriptionRun.weightDefined = false;
353   fontDescriptionRun.widthDefined  = false;
354   fontDescriptionRun.slantDefined  = false;
355   fontDescriptionRun.sizeDefined   = false;
356
357   Vector<FontDescriptionRun> fontDescriptionRuns;
358   fontDescriptionRuns.PushBack(fontDescriptionRun);
359   Size textArea(1.f, 1.f);
360
361   //******* characterSpacing = 0.0f *******//
362   float positions[] = {
363     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};
364   Size layoutSize(81.f, 20.f);
365   //************************************//
366
367   struct LineRun line =
368     {
369       {0u, 11u},
370       {0u, 11u},
371       81.f,
372       15.f,
373       -5.f,
374       0.f,
375       0.f,
376       0.f,
377       false,
378       false};
379   Vector<LineRun> lines;
380   lines.PushBack(line);
381
382   LayoutTextData data =
383     {
384       "Layout text in a small area",
385       "Hello world",
386       textArea,
387       1u,
388       fontDescriptionRuns.Begin(),
389       layoutSize,
390       11u,
391       positions,
392       1u,
393       lines.Begin(),
394       Layout::Engine::SINGLE_LINE_BOX,
395       0u,
396       11u,
397       false,
398       true,
399       0.0f};
400
401   if(!LayoutTextTest(data))
402   {
403     tet_result(TET_FAIL);
404   }
405
406   tet_result(TET_PASS);
407   END_TEST;
408 }
409
410 int UtcDaliTextCharacterSpacingSingleLineTextArea2(void)
411 {
412   ToolkitTestApplication application;
413   tet_infoline(" UtcDaliTextCharacterSpacingSingleLineTextArea2");
414
415   // Will layout the text in single line as it can be scrolled.
416
417   const std::string fontFamily("TizenSans");
418
419   // Set a known font description
420   FontDescriptionRun fontDescriptionRun;
421   fontDescriptionRun.characterRun.characterIndex     = 0u;
422   fontDescriptionRun.characterRun.numberOfCharacters = 11u;
423   fontDescriptionRun.familyLength                    = fontFamily.size();
424   fontDescriptionRun.familyName                      = new char[fontDescriptionRun.familyLength];
425   memcpy(fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength);
426   fontDescriptionRun.familyDefined = true;
427   fontDescriptionRun.weightDefined = false;
428   fontDescriptionRun.widthDefined  = false;
429   fontDescriptionRun.slantDefined  = false;
430   fontDescriptionRun.sizeDefined   = false;
431
432   Vector<FontDescriptionRun> fontDescriptionRuns;
433   fontDescriptionRuns.PushBack(fontDescriptionRun);
434   Size textArea(1.f, 1.f);
435
436   //******* characterSpacing = 2.0f *******//
437   float positions[] = {
438     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};
439   Size layoutSize(101.f, 20.f);
440   //************************************//
441
442   struct LineRun line =
443     {
444       {0u, 11u},
445       {0u, 11u},
446       101.f,
447       15.f,
448       -5.f,
449       0.f,
450       0.f,
451       0.f,
452       false,
453       false};
454   Vector<LineRun> lines;
455   lines.PushBack(line);
456
457   LayoutTextData data =
458     {
459       "Layout text in a small area",
460       "Hello world",
461       textArea,
462       1u,
463       fontDescriptionRuns.Begin(),
464       layoutSize,
465       11u,
466       positions,
467       1u,
468       lines.Begin(),
469       Layout::Engine::SINGLE_LINE_BOX,
470       0u,
471       11u,
472       false,
473       true,
474       2.0f};
475
476   if(!LayoutTextTest(data))
477   {
478     tet_result(TET_FAIL);
479   }
480
481   tet_result(TET_PASS);
482   END_TEST;
483 }
484
485 int UtcDaliTextCharacterSpacingSingleLineTextArea3(void)
486 {
487   ToolkitTestApplication application;
488   tet_infoline(" UtcDaliTextCharacterSpacingSingleLineTextArea3");
489
490   // Will layout the text in single line as it can be scrolled.
491
492   const std::string fontFamily("TizenSans");
493
494   // Set a known font description
495   FontDescriptionRun fontDescriptionRun;
496   fontDescriptionRun.characterRun.characterIndex     = 0u;
497   fontDescriptionRun.characterRun.numberOfCharacters = 11u;
498   fontDescriptionRun.familyLength                    = fontFamily.size();
499   fontDescriptionRun.familyName                      = new char[fontDescriptionRun.familyLength];
500   memcpy(fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength);
501   fontDescriptionRun.familyDefined = true;
502   fontDescriptionRun.weightDefined = false;
503   fontDescriptionRun.widthDefined  = false;
504   fontDescriptionRun.slantDefined  = false;
505   fontDescriptionRun.sizeDefined   = false;
506
507   Vector<FontDescriptionRun> fontDescriptionRuns;
508   fontDescriptionRuns.PushBack(fontDescriptionRun);
509   Size textArea(1.f, 1.f);
510
511   //******* characterSpacing = 4.0f *******//
512   float positions[] = {
513     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};
514   Size layoutSize(121.f, 20.f);
515   //************************************//
516
517   struct LineRun line =
518     {
519       {0u, 11u},
520       {0u, 11u},
521       121.f,
522       15.f,
523       -5.f,
524       0.f,
525       0.f,
526       0.f,
527       false,
528       false};
529   Vector<LineRun> lines;
530   lines.PushBack(line);
531
532   LayoutTextData data =
533     {
534       "Layout text in a small area",
535       "Hello world",
536       textArea,
537       1u,
538       fontDescriptionRuns.Begin(),
539       layoutSize,
540       11u,
541       positions,
542       1u,
543       lines.Begin(),
544       Layout::Engine::SINGLE_LINE_BOX,
545       0u,
546       11u,
547       false,
548       true,
549       4.0f};
550
551   if(!LayoutTextTest(data))
552   {
553     tet_result(TET_FAIL);
554   }
555
556   tet_result(TET_PASS);
557   END_TEST;
558 }
559
560 int UtcDaliTextCharacterSpacingMultilineText1(void)
561 {
562   ToolkitTestApplication application;
563   tet_infoline(" UtcDaliTextCharacterSpacingMultilineText1");
564
565   // Layout some lines of left to right text.
566
567   const std::string fontFamily("TizenSans");
568
569   // Set a known font description
570   FontDescriptionRun fontDescriptionRun1;
571   fontDescriptionRun1.characterRun.characterIndex     = 0u;
572   fontDescriptionRun1.characterRun.numberOfCharacters = 18u;
573   fontDescriptionRun1.familyLength                    = fontFamily.size();
574   fontDescriptionRun1.familyName                      = new char[fontDescriptionRun1.familyLength];
575   memcpy(fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength);
576   fontDescriptionRun1.familyDefined = true;
577   fontDescriptionRun1.weightDefined = false;
578   fontDescriptionRun1.widthDefined  = false;
579   fontDescriptionRun1.slantDefined  = false;
580   fontDescriptionRun1.sizeDefined   = false;
581
582   FontDescriptionRun fontDescriptionRun2;
583   fontDescriptionRun2.characterRun.characterIndex     = 18u;
584   fontDescriptionRun2.characterRun.numberOfCharacters = 31u;
585   fontDescriptionRun2.familyLength                    = fontFamily.size();
586   fontDescriptionRun2.familyName                      = new char[fontDescriptionRun2.familyLength];
587   memcpy(fontDescriptionRun2.familyName, fontFamily.c_str(), fontDescriptionRun2.familyLength);
588   fontDescriptionRun2.familyDefined = true;
589   fontDescriptionRun2.weightDefined = false;
590   fontDescriptionRun2.widthDefined  = false;
591   fontDescriptionRun2.slantDefined  = false;
592   fontDescriptionRun2.sizeDefined   = false;
593
594   Vector<FontDescriptionRun> fontDescriptionRuns;
595   fontDescriptionRuns.PushBack(fontDescriptionRun1);
596   fontDescriptionRuns.PushBack(fontDescriptionRun2);
597   Size  textArea(100.f, 300.f);
598   Size  layoutSize(98.f, 97.f);
599   float positions[] =
600     {
601       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};
602   struct LineRun line0 =
603     {
604       {0u, 12u},
605       {0u, 12u},
606       81.f,
607       15.f,
608       -5.f,
609       4.f,
610       0.f,
611       0.f,
612       false,
613       false};
614   struct LineRun line1 =
615     {
616       {12u, 6u},
617       {12u, 6u},
618       44.f,
619       15.f,
620       -5.f,
621       0.f,
622       0.f,
623       0.f,
624       false,
625       false};
626   struct LineRun line2 =
627     {
628       {18u, 7u},
629       {18u, 7u},
630       54.f,
631       15.f,
632       -4.f,
633       6.f,
634       0.f,
635       0.f,
636       false,
637       false};
638   struct LineRun line3 =
639     {
640       {25u, 9u},
641       {25u, 10u},
642       68.f,
643       15.f,
644       -4.f,
645       6.f,
646       0.f,
647       0.f,
648       false,
649       false};
650   struct LineRun line4 =
651     {
652       {34u, 14u},
653       {35u, 14u},
654       98.f,
655       15.f,
656       -4.f,
657       0.f,
658       0.f,
659       0.f,
660       false,
661       false};
662   Vector<LineRun> lines;
663   lines.PushBack(line0);
664   lines.PushBack(line1);
665   lines.PushBack(line2);
666   lines.PushBack(line3);
667   lines.PushBack(line4);
668
669   LayoutTextData data =
670     {
671       "Layout simple multiline text",
672       "Hello world demo.\n"
673       "Layout different lines of text.",
674       textArea,
675       1u,
676       fontDescriptionRuns.Begin(),
677       layoutSize,
678       48u,
679       positions,
680       5u,
681       lines.Begin(),
682       Layout::Engine::MULTI_LINE_BOX,
683       0u,
684       48u,
685       false,
686       true,
687       0.0f};
688
689   if(!LayoutTextTest(data))
690   {
691     tet_result(TET_FAIL);
692   }
693
694   tet_result(TET_PASS);
695   END_TEST;
696 }
697
698 int UtcDaliTextCharacterSpacingMultilineText2(void)
699 {
700   ToolkitTestApplication application;
701   tet_infoline(" UtcDaliTextCharacterSpacingMultilineText2");
702
703   // Layout some lines of left to right text.
704
705   const std::string fontFamily("TizenSans");
706
707   // Set a known font description
708   FontDescriptionRun fontDescriptionRun1;
709   fontDescriptionRun1.characterRun.characterIndex     = 0u;
710   fontDescriptionRun1.characterRun.numberOfCharacters = 18u;
711   fontDescriptionRun1.familyLength                    = fontFamily.size();
712   fontDescriptionRun1.familyName                      = new char[fontDescriptionRun1.familyLength];
713   memcpy(fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength);
714   fontDescriptionRun1.familyDefined = true;
715   fontDescriptionRun1.weightDefined = false;
716   fontDescriptionRun1.widthDefined  = false;
717   fontDescriptionRun1.slantDefined  = false;
718   fontDescriptionRun1.sizeDefined   = false;
719
720   FontDescriptionRun fontDescriptionRun2;
721   fontDescriptionRun2.characterRun.characterIndex     = 18u;
722   fontDescriptionRun2.characterRun.numberOfCharacters = 31u;
723   fontDescriptionRun2.familyLength                    = fontFamily.size();
724   fontDescriptionRun2.familyName                      = new char[fontDescriptionRun2.familyLength];
725   memcpy(fontDescriptionRun2.familyName, fontFamily.c_str(), fontDescriptionRun2.familyLength);
726   fontDescriptionRun2.familyDefined = true;
727   fontDescriptionRun2.weightDefined = false;
728   fontDescriptionRun2.widthDefined  = false;
729   fontDescriptionRun2.slantDefined  = false;
730   fontDescriptionRun2.sizeDefined   = false;
731
732   Vector<FontDescriptionRun> fontDescriptionRuns;
733   fontDescriptionRuns.PushBack(fontDescriptionRun1);
734   fontDescriptionRuns.PushBack(fontDescriptionRun2);
735   Size  textArea(100.f, 300.f);
736   Size  layoutSize(82.f, 136.f);
737   float positions[] =
738     {
739       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};
740   struct LineRun line0 =
741     {
742       {0u, 6u},
743       {0u, 6u},
744       44.f,
745       15.f,
746       -5.f,
747       6.f,
748       0.f,
749       0.f,
750       false,
751       false};
752   struct LineRun line1 =
753     {
754       {6u, 6u},
755       {6u, 6u},
756       49.f,
757       15.f,
758       -5.f,
759       6.f,
760       0.f,
761       0.f,
762       false,
763       false};
764   struct LineRun line2 =
765     {
766       {12u, 6u},
767       {12u, 6u},
768       52.f,
769       15.f,
770       -5.f,
771       0.f,
772       0.f,
773       0.f,
774       false,
775       false};
776   struct LineRun line3 =
777     {
778       {18u, 7u},
779       {18u, 7u},
780       64.f,
781       15.f,
782       -4.f,
783       8.f,
784       0.f,
785       0.f,
786       false,
787       false};
788   struct LineRun line4 =
789     {
790       {25u, 9u},
791       {25u, 10u},
792       82.f,
793       15.f,
794       -4.f,
795       8.f,
796       0.f,
797       0.f,
798       false,
799       false};
800   struct LineRun line5 =
801     {
802       {34u, 9u},
803       {35u, 9u},
804       72.f,
805       15.f,
806       -4.f,
807       8.f,
808       0.f,
809       0.f,
810       false,
811       false};
812   struct LineRun line6 =
813     {
814       {43u, 5u},
815       {44u, 5u},
816       44.f,
817       15.f,
818       -4.f,
819       0.f,
820       0.f,
821       0.f,
822       false,
823       false};
824   Vector<LineRun> lines;
825   lines.PushBack(line0);
826   lines.PushBack(line1);
827   lines.PushBack(line2);
828   lines.PushBack(line3);
829   lines.PushBack(line4);
830   lines.PushBack(line5);
831   lines.PushBack(line6);
832
833   LayoutTextData data =
834     {
835       "Layout simple multiline text",
836       "Hello world demo.\n"
837       "Layout different lines of text.",
838       textArea,
839       1u,
840       fontDescriptionRuns.Begin(),
841       layoutSize,
842       48u,
843       positions,
844       7u,
845       lines.Begin(),
846       Layout::Engine::MULTI_LINE_BOX,
847       0u,
848       48u,
849       false,
850       true,
851       2.0f};
852
853   if(!LayoutTextTest(data))
854   {
855     tet_result(TET_FAIL);
856   }
857
858   tet_result(TET_PASS);
859   END_TEST;
860 }