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