[dali_2.3.20] 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     // Do not compare the alignment offset as it's not calculated in the layout.
314     // Do not compare the line direction as it's not set in the layout.
315   }
316
317   return true;
318 }
319
320 ////////////////////////////////////////////////////////
321
322 } // namespace
323
324 //////////////////////////////////////////////////////////
325 //
326 // UtcDaliTextCharacterSpacingSingleLineTextArea1
327 // UtcDaliTextCharacterSpacingSingleLineTextArea2
328 // UtcDaliTextCharacterSpacingSingleLineTextArea3
329 // UtcDaliTextCharacterSpacingMultilineText1
330 // UtcDaliTextCharacterSpacingMultilineText2
331 //
332 //////////////////////////////////////////////////////////
333
334 int UtcDaliTextCharacterSpacingSingleLineTextArea1(void)
335 {
336   ToolkitTestApplication application;
337   tet_infoline(" UtcDaliTextCharacterSpacingSingleLineTextArea1");
338
339   // Will layout the text in single line as it can be scrolled.
340
341   const std::string fontFamily("TizenSans");
342
343   // Set a known font description
344   FontDescriptionRun fontDescriptionRun;
345   fontDescriptionRun.characterRun.characterIndex     = 0u;
346   fontDescriptionRun.characterRun.numberOfCharacters = 11u;
347   fontDescriptionRun.familyLength                    = fontFamily.size();
348   fontDescriptionRun.familyName                      = new char[fontDescriptionRun.familyLength];
349   memcpy(fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength);
350   fontDescriptionRun.familyDefined = true;
351   fontDescriptionRun.weightDefined = false;
352   fontDescriptionRun.widthDefined  = false;
353   fontDescriptionRun.slantDefined  = false;
354   fontDescriptionRun.sizeDefined   = false;
355
356   Vector<FontDescriptionRun> fontDescriptionRuns;
357   fontDescriptionRuns.PushBack(fontDescriptionRun);
358   Size textArea(1.f, 1.f);
359
360   //******* characterSpacing = 0.0f *******//
361   float positions[] =
362    {
363     0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f
364    };
365   Size layoutSize(79.f, 20.f);
366   //************************************//
367
368   struct LineRun line =
369     {
370       {0u, 11u},
371       {0u, 11u},
372       79.f,
373       15.f,
374       -5.f,
375       0.f,
376       0.f,
377       0.f,
378       false,
379       false};
380   Vector<LineRun> lines;
381   lines.PushBack(line);
382
383   LayoutTextData data =
384     {
385       "Layout text in a small area",
386       "Hello world",
387       textArea,
388       1u,
389       fontDescriptionRuns.Begin(),
390       layoutSize,
391       11u,
392       positions,
393       1u,
394       lines.Begin(),
395       Layout::Engine::SINGLE_LINE_BOX,
396       0u,
397       11u,
398       false,
399       true,
400       0.0f};
401
402   if(!LayoutTextTest(data))
403   {
404     tet_result(TET_FAIL);
405   }
406
407   tet_result(TET_PASS);
408   END_TEST;
409 }
410
411 int UtcDaliTextCharacterSpacingSingleLineTextArea2(void)
412 {
413   ToolkitTestApplication application;
414   tet_infoline(" UtcDaliTextCharacterSpacingSingleLineTextArea2");
415
416   // Will layout the text in single line as it can be scrolled.
417
418   const std::string fontFamily("TizenSans");
419
420   // Set a known font description
421   FontDescriptionRun fontDescriptionRun;
422   fontDescriptionRun.characterRun.characterIndex     = 0u;
423   fontDescriptionRun.characterRun.numberOfCharacters = 11u;
424   fontDescriptionRun.familyLength                    = fontFamily.size();
425   fontDescriptionRun.familyName                      = new char[fontDescriptionRun.familyLength];
426   memcpy(fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength);
427   fontDescriptionRun.familyDefined = true;
428   fontDescriptionRun.weightDefined = false;
429   fontDescriptionRun.widthDefined  = false;
430   fontDescriptionRun.slantDefined  = false;
431   fontDescriptionRun.sizeDefined   = false;
432
433   Vector<FontDescriptionRun> fontDescriptionRuns;
434   fontDescriptionRuns.PushBack(fontDescriptionRun);
435   Size textArea(1.f, 1.f);
436
437   //******* characterSpacing = 2.0f *******//
438   float positions[] =
439    {
440      0.f, -12.f, 12.f, -9.f, 23.f, -13.f, 29.f, -13.f, 34.f, -9.f, 45.f, -0.f, 51.f, -9.f, 65.f, -9.f, 77.f, -9.f, 85.f, -13.f, 90.f, -13.f
441    };
442   Size layoutSize(99.f, 20.f);
443   //************************************//
444
445   struct LineRun line =
446     {
447       {0u, 11u},
448       {0u, 11u},
449       99.f,
450       15.f,
451       -5.f,
452       0.f,
453       0.f,
454       0.f,
455       false,
456       false};
457   Vector<LineRun> lines;
458   lines.PushBack(line);
459
460   LayoutTextData data =
461     {
462       "Layout text in a small area",
463       "Hello world",
464       textArea,
465       1u,
466       fontDescriptionRuns.Begin(),
467       layoutSize,
468       11u,
469       positions,
470       1u,
471       lines.Begin(),
472       Layout::Engine::SINGLE_LINE_BOX,
473       0u,
474       11u,
475       false,
476       true,
477       2.0f};
478
479   if(!LayoutTextTest(data))
480   {
481     tet_result(TET_FAIL);
482   }
483
484   tet_result(TET_PASS);
485   END_TEST;
486 }
487
488 int UtcDaliTextCharacterSpacingSingleLineTextArea3(void)
489 {
490   ToolkitTestApplication application;
491   tet_infoline(" UtcDaliTextCharacterSpacingSingleLineTextArea3");
492
493   // Will layout the text in single line as it can be scrolled.
494
495   const std::string fontFamily("TizenSans");
496
497   // Set a known font description
498   FontDescriptionRun fontDescriptionRun;
499   fontDescriptionRun.characterRun.characterIndex     = 0u;
500   fontDescriptionRun.characterRun.numberOfCharacters = 11u;
501   fontDescriptionRun.familyLength                    = fontFamily.size();
502   fontDescriptionRun.familyName                      = new char[fontDescriptionRun.familyLength];
503   memcpy(fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength);
504   fontDescriptionRun.familyDefined = true;
505   fontDescriptionRun.weightDefined = false;
506   fontDescriptionRun.widthDefined  = false;
507   fontDescriptionRun.slantDefined  = false;
508   fontDescriptionRun.sizeDefined   = false;
509
510   Vector<FontDescriptionRun> fontDescriptionRuns;
511   fontDescriptionRuns.PushBack(fontDescriptionRun);
512   Size textArea(1.f, 1.f);
513
514   //******* characterSpacing = 4.0f *******//
515   float positions[] =
516    {
517      0.f, -12.f, 14.f, -9.f, 27.f, -13.f, 35.f, -13.f, 42.f, -9.f, 55.f, -0.f, 63.f, -9.f, 79.f, -9.f, 93.f, -9.f, 103.f, -13.f, 110.f, -13.f
518    };
519   Size layoutSize(119.f, 20.f);
520   //************************************//
521
522   struct LineRun line =
523     {
524       {0u, 11u},
525       {0u, 11u},
526       119.f,
527       15.f,
528       -5.f,
529       0.f,
530       0.f,
531       0.f,
532       false,
533       false};
534   Vector<LineRun> lines;
535   lines.PushBack(line);
536
537   LayoutTextData data =
538     {
539       "Layout text in a small area",
540       "Hello world",
541       textArea,
542       1u,
543       fontDescriptionRuns.Begin(),
544       layoutSize,
545       11u,
546       positions,
547       1u,
548       lines.Begin(),
549       Layout::Engine::SINGLE_LINE_BOX,
550       0u,
551       11u,
552       false,
553       true,
554       4.0f};
555
556   if(!LayoutTextTest(data))
557   {
558     tet_result(TET_FAIL);
559   }
560
561   tet_result(TET_PASS);
562   END_TEST;
563 }
564
565 int UtcDaliTextCharacterSpacingMultilineText1(void)
566 {
567   ToolkitTestApplication application;
568   tet_infoline(" UtcDaliTextCharacterSpacingMultilineText1");
569
570   // Layout some lines of left to right text.
571
572   const std::string fontFamily("TizenSans");
573
574   // Set a known font description
575   FontDescriptionRun fontDescriptionRun1;
576   fontDescriptionRun1.characterRun.characterIndex     = 0u;
577   fontDescriptionRun1.characterRun.numberOfCharacters = 18u;
578   fontDescriptionRun1.familyLength                    = fontFamily.size();
579   fontDescriptionRun1.familyName                      = new char[fontDescriptionRun1.familyLength];
580   memcpy(fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength);
581   fontDescriptionRun1.familyDefined = true;
582   fontDescriptionRun1.weightDefined = false;
583   fontDescriptionRun1.widthDefined  = false;
584   fontDescriptionRun1.slantDefined  = false;
585   fontDescriptionRun1.sizeDefined   = false;
586
587   FontDescriptionRun fontDescriptionRun2;
588   fontDescriptionRun2.characterRun.characterIndex     = 18u;
589   fontDescriptionRun2.characterRun.numberOfCharacters = 31u;
590   fontDescriptionRun2.familyLength                    = fontFamily.size();
591   fontDescriptionRun2.familyName                      = new char[fontDescriptionRun2.familyLength];
592   memcpy(fontDescriptionRun2.familyName, fontFamily.c_str(), fontDescriptionRun2.familyLength);
593   fontDescriptionRun2.familyDefined = true;
594   fontDescriptionRun2.weightDefined = false;
595   fontDescriptionRun2.widthDefined  = false;
596   fontDescriptionRun2.slantDefined  = false;
597   fontDescriptionRun2.sizeDefined   = false;
598
599   Vector<FontDescriptionRun> fontDescriptionRuns;
600   fontDescriptionRuns.PushBack(fontDescriptionRun1);
601   fontDescriptionRuns.PushBack(fontDescriptionRun2);
602   Size  textArea(100.f, 300.f);
603   Size  layoutSize(96.f, 97.f);
604   float positions[] =
605     {
606       0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f, 0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 31.f, -9.f, 40.f, -2.f, 44.f, -12.f, 0.f, -12.f, 8.f, -9.f, 18.f, -9.f, 27.f, -9.f, 38.f, -9.f, 47.f, -11.f, 53.f, -0.f, 0.f, -12.f, 11.f, -12.f, 14.f, -12.f, 25.f, -9.f, 36.f, -9.f, 41.f, -9.f, 52.f, -9.f, 61.f, -11.f, 67.f, -0.f, 0.f, -12.f, 4.f, -12.f, 8.f, -9.f, 17.f, -9.f, 27.f, -9.f, 35.f, -0.f, 40.f, -9.f, 50.f, -12.f, 56.f, -0.f, 61.f, -11.f, 67.f, -9.f, 77.f, -9.f, 86.f, -11.f, 93.f, -2.f
607     };
608   struct LineRun line0 =
609     {
610       {0u, 12u},
611       {0u, 12u},
612       79.f,
613       15.f,
614       -5.f,
615       4.f,
616       0.f,
617       0.f,
618       false,
619       false};
620   struct LineRun line1 =
621     {
622       {12u, 6u},
623       {12u, 6u},
624       43.f,
625       15.f,
626       -5.f,
627       0.f,
628       0.f,
629       0.f,
630       false,
631       false};
632   struct LineRun line2 =
633     {
634       {18u, 7u},
635       {18u, 7u},
636       53.f,
637       15.f,
638       -4.f,
639       5.f,
640       0.f,
641       0.f,
642       false,
643       false};
644   struct LineRun line3 =
645     {
646       {25u, 9u},
647       {25u, 10u},
648       67.f,
649       15.f,
650       -4.f,
651       5.f,
652       0.f,
653       0.f,
654       false,
655       false};
656   struct LineRun line4 =
657     {
658       {34u, 14u},
659       {35u, 14u},
660       96.f,
661       15.f,
662       -4.f,
663       0.f,
664       0.f,
665       0.f,
666       false,
667       false};
668   Vector<LineRun> lines;
669   lines.PushBack(line0);
670   lines.PushBack(line1);
671   lines.PushBack(line2);
672   lines.PushBack(line3);
673   lines.PushBack(line4);
674
675   LayoutTextData data =
676     {
677       "Layout simple multiline text",
678       "Hello world demo.\n"
679       "Layout different lines of text.",
680       textArea,
681       1u,
682       fontDescriptionRuns.Begin(),
683       layoutSize,
684       48u,
685       positions,
686       5u,
687       lines.Begin(),
688       Layout::Engine::MULTI_LINE_BOX,
689       0u,
690       48u,
691       false,
692       true,
693       0.0f};
694
695   if(!LayoutTextTest(data))
696   {
697     tet_result(TET_FAIL);
698   }
699
700   tet_result(TET_PASS);
701   END_TEST;
702 }
703
704 int UtcDaliTextCharacterSpacingMultilineText2(void)
705 {
706   ToolkitTestApplication application;
707   tet_infoline(" UtcDaliTextCharacterSpacingMultilineText2");
708
709   // Layout some lines of left to right text.
710
711   const std::string fontFamily("TizenSans");
712
713   // Set a known font description
714   FontDescriptionRun fontDescriptionRun1;
715   fontDescriptionRun1.characterRun.characterIndex     = 0u;
716   fontDescriptionRun1.characterRun.numberOfCharacters = 18u;
717   fontDescriptionRun1.familyLength                    = fontFamily.size();
718   fontDescriptionRun1.familyName                      = new char[fontDescriptionRun1.familyLength];
719   memcpy(fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength);
720   fontDescriptionRun1.familyDefined = true;
721   fontDescriptionRun1.weightDefined = false;
722   fontDescriptionRun1.widthDefined  = false;
723   fontDescriptionRun1.slantDefined  = false;
724   fontDescriptionRun1.sizeDefined   = false;
725
726   FontDescriptionRun fontDescriptionRun2;
727   fontDescriptionRun2.characterRun.characterIndex     = 18u;
728   fontDescriptionRun2.characterRun.numberOfCharacters = 31u;
729   fontDescriptionRun2.familyLength                    = fontFamily.size();
730   fontDescriptionRun2.familyName                      = new char[fontDescriptionRun2.familyLength];
731   memcpy(fontDescriptionRun2.familyName, fontFamily.c_str(), fontDescriptionRun2.familyLength);
732   fontDescriptionRun2.familyDefined = true;
733   fontDescriptionRun2.weightDefined = false;
734   fontDescriptionRun2.widthDefined  = false;
735   fontDescriptionRun2.slantDefined  = false;
736   fontDescriptionRun2.sizeDefined   = false;
737
738   Vector<FontDescriptionRun> fontDescriptionRuns;
739   fontDescriptionRuns.PushBack(fontDescriptionRun1);
740   fontDescriptionRuns.PushBack(fontDescriptionRun2);
741   Size  textArea(100.f, 300.f);
742   Size  layoutSize(99.f, 116.f);
743   float positions[] =
744     {
745       0.f, -12.f, 12.f, -9.f, 23.f, -13.f, 29.f, -13.f, 34.f, -9.f, 45.f, -0.f, 51.f, -9.f, 65.f, -9.f, 77.f, -9.f, 85.f, -13.f, 90.f, -13.f, 101.f, -0.f, 0.f, -13.f, 11.f, -9.f, 22.f, -9.f, 37.f, -9.f, 48.f, -2.f, 54.f, -12.f, 0.f, -12.f, 10.f, -9.f, 22.f, -9.f, 33.f, -9.f, 46.f, -9.f, 57.f, -11.f, 65.f, -0.f, 0.f, -12.f, 13.f, -12.f, 18.f, -12.f, 31.f, -9.f, 44.f, -9.f, 51.f, -9.f, 64.f, -9.f, 75.f, -11.f, 83.f, -0.f, 0.f, -12.f, 6.f, -12.f, 12.f, -9.f, 23.f, -9.f, 35.f, -9.f, 45.f, -0.f, 52.f, -9.f, 64.f, -12.f, 72.f, -0.f, 0.f, -11.f, 8.f, -9.f, 20.f, -9.f, 31.f, -11.f, 40.f, -2.f
746     };
747   struct LineRun line0 =
748     {
749       {0u, 12u},
750       {0u, 12u},
751       99.f,
752       15.f,
753       -5.f,
754       6.f,
755       0.f,
756       0.f,
757       false,
758       false};
759   struct LineRun line1 =
760     {
761       {12u, 6u},
762       {12u, 6u},
763       51.f,
764       15.f,
765       -5.f,
766       0.f,
767       0.f,
768       0.f,
769       false,
770       false};
771   struct LineRun line2 =
772     {
773       {18u, 7u},
774       {18u, 7u},
775       63.f,
776       15.f,
777       -4.f,
778       7.f,
779       0.f,
780       0.f,
781       false,
782       false};
783   struct LineRun line3 =
784     {
785       {25u, 9u},
786       {25u, 10u},
787       81.f,
788       15.f,
789       -4.f,
790       7.f,
791       0.f,
792       0.f,
793       false,
794       false};
795   struct LineRun line4 =
796     {
797       {34u, 9u},
798       {35u, 9u},
799       70.f,
800       15.f,
801       -4.f,
802       7.f,
803       0.f,
804       0.f,
805       false,
806       false};
807   struct LineRun line5 =
808     {
809       {43u, 5u},
810       {44u, 5u},
811       43.f,
812       15.f,
813       -4.f,
814       0.f,
815       0.f,
816       0.f,
817       false,
818       false};
819   Vector<LineRun> lines;
820   lines.PushBack(line0);
821   lines.PushBack(line1);
822   lines.PushBack(line2);
823   lines.PushBack(line3);
824   lines.PushBack(line4);
825   lines.PushBack(line5);
826
827   LayoutTextData data =
828     {
829       "Layout simple multiline text",
830       "Hello world demo.\n"
831       "Layout different lines of text.",
832       textArea,
833       1u,
834       fontDescriptionRuns.Begin(),
835       layoutSize,
836       48u,
837       positions,
838       6u,
839       lines.Begin(),
840       Layout::Engine::MULTI_LINE_BOX,
841       0u,
842       48u,
843       false,
844       true,
845       2.0f};
846
847   if(!LayoutTextTest(data))
848   {
849     tet_result(TET_FAIL);
850   }
851
852   tet_result(TET_PASS);
853   END_TEST;
854 }