ebbf65bf447cdc3825a14a4b611f7e61f87521d2
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / layouts / layout-engine.cpp
1 /*
2  * Copyright (c) 2015 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 // CLASS HEADER
19 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/math/vector2.h>
23 #include <dali/public-api/text-abstraction/font-client.h>
24
25 // INTERNAL INCLUDES
26 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
27 #include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
28
29 namespace Dali
30 {
31
32 namespace Toolkit
33 {
34
35 namespace Text
36 {
37
38 /**
39  * @brief Stores temporary layout info of the line.
40  */
41 struct LineLayout
42 {
43   GlyphIndex     glyphIndex;         ///< Index of the first glyph to be laid-out.
44   CharacterIndex characterIndex;     ///< Index of the first character to be laid-out.
45   Length         numberOfCharacters; ///< The number of characters which fit in one line.
46   Length         numberOfGlyphs;     ///< The number of glyph which fit in one line.
47   float          length;             ///< The length of the glyphs which fit in one line.
48   float          widthAdvanceDiff;   ///< The difference between the width and the advance of the last glyph.
49   float          wsLengthEndOfLine;  ///< The length of the white spaces at the end of the line.
50   float          ascender;           ///< The maximum ascender of all fonts in the line.
51   float          descender;          ///< The maximum descender of all fonts in the line.
52 };
53
54 struct LayoutEngine::Impl
55 {
56   Impl()
57   : mLayout( LayoutEngine::SINGLE_LINE_BOX ),
58     mAlignment( LayoutEngine::ALIGN_BEGIN )
59   {
60     mFontClient = TextAbstraction::FontClient::Get();
61   }
62
63   /**
64    * Retrieves the line layout for a given box width.
65    */
66   void GetLineLayoutForBox( const LayoutParameters& parameters,
67                             LineLayout& lineLayout )
68   {
69     // Initializes the line layout.
70     lineLayout.numberOfCharacters = 0u;
71     lineLayout.numberOfGlyphs = 0u;
72     lineLayout.length = 0.f;
73     lineLayout.wsLengthEndOfLine = 0.f;
74     lineLayout.ascender = 0.f;
75     lineLayout.descender = 0.f;
76
77     // Get the last glyph index.
78     const GlyphIndex lastGlyphIndex = parameters.totalNumberOfGlyphs - 1u;
79
80     FontId lastFontId = 0u;
81     for( GlyphIndex glyphIndex = lineLayout.glyphIndex;
82          glyphIndex < parameters.totalNumberOfGlyphs;
83          ++glyphIndex )
84     {
85       // Get the glyph info.
86       const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + glyphIndex );
87
88       // Check whether is a white space.
89       const Character character = *( parameters.textBuffer + lineLayout.numberOfCharacters );
90       const bool isWhiteSpace = TextAbstraction::IsWhiteSpace( character );
91
92       // Get the character indices for the current glyph. The last character index is needed
93       // because there are glyphs formed by more than one character but their break info is
94       // given only for the last character.
95       const Length charactersPerGlyph = *( parameters.charactersPerGlyphBuffer + glyphIndex );
96
97       // Increase the number of characters.
98       lineLayout.numberOfCharacters += charactersPerGlyph;
99
100       // Increase the number of glyphs.
101       lineLayout.numberOfGlyphs++;
102
103       // Increase the accumulated length.
104       const float glyphLength = ( glyphIndex == lastGlyphIndex ) ? glyphInfo.width : glyphInfo.advance;
105
106       if( isWhiteSpace )
107       {
108         // Add the length to the length of white spaces at the end of the line.
109         lineLayout.wsLengthEndOfLine += glyphLength;
110       }
111       else
112       {
113         // Add as well any previous white space length.
114         lineLayout.length += lineLayout.wsLengthEndOfLine + glyphLength;
115
116         // Clear the white space length at the end of the line.
117         lineLayout.wsLengthEndOfLine = 0.f;
118       }
119
120       if( lastFontId != glyphInfo.fontId )
121       {
122         Text::FontMetrics fontMetrics;
123         mFontClient.GetFontMetrics( glyphInfo.fontId, fontMetrics );
124
125         // Sets the maximum ascender.
126         if( fontMetrics.ascender > lineLayout.ascender )
127         {
128           lineLayout.ascender = fontMetrics.ascender;
129         }
130
131         // Sets the maximum descender.
132         if( fontMetrics.descender > lineLayout.descender )
133         {
134           lineLayout.descender = fontMetrics.descender;
135         }
136
137         lastFontId = glyphInfo.fontId;
138       }
139     }
140   }
141
142   /**
143    * Retrieves the line layout for a given box width.
144    */
145   void GetMultiLineLayoutForBox( const LayoutParameters& parameters,
146                                  LineLayout& lineLayout )
147   {
148     // Initializes the line layout.
149     lineLayout.numberOfCharacters = 0u;
150     lineLayout.numberOfGlyphs = 0u;
151     lineLayout.length = 0.f;
152     lineLayout.widthAdvanceDiff = 0.f;
153     lineLayout.wsLengthEndOfLine = 0.f;
154     lineLayout.ascender = 0.f;
155     lineLayout.descender = 0.f;
156
157     // Stores temporary line layout which has not been added to the final line layout.
158     LineLayout tmpLineLayout;
159     tmpLineLayout.numberOfCharacters = 0u;
160     tmpLineLayout.numberOfGlyphs = 0u;
161     tmpLineLayout.length = 0.f;
162     tmpLineLayout.widthAdvanceDiff = 0.f;
163     tmpLineLayout.wsLengthEndOfLine = 0.f;
164     tmpLineLayout.ascender = 0.f;
165     tmpLineLayout.descender = 0.f;
166
167     FontId lastFontId = 0u;
168     for( GlyphIndex glyphIndex = lineLayout.glyphIndex;
169          glyphIndex < parameters.totalNumberOfGlyphs;
170          ++glyphIndex )
171     {
172       // Get the glyph info.
173       const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + glyphIndex );
174
175       // Get the character indices for the current glyph. The last character index is needed
176       // because there are glyphs formed by more than one character but their break info is
177       // given only for the last character.
178       const Length charactersPerGlyph = *( parameters.charactersPerGlyphBuffer + glyphIndex );
179       const CharacterIndex characterFirstIndex = *( parameters.glyphsToCharactersBuffer + glyphIndex );
180       const CharacterIndex characterLastIndex = characterFirstIndex + ( ( 1u > charactersPerGlyph ) ? 0u : charactersPerGlyph - 1u );
181
182       // Get the line break info for the current character.
183       const LineBreakInfo lineBreakInfo = *( parameters.lineBreakInfoBuffer + characterLastIndex );
184
185       // Get the word break info for the current character.
186       const WordBreakInfo wordBreakInfo = *( parameters.wordBreakInfoBuffer + characterLastIndex );
187
188       // Increase the number of characters.
189       tmpLineLayout.numberOfCharacters += charactersPerGlyph;
190
191       // Increase the number of glyphs.
192       tmpLineLayout.numberOfGlyphs++;
193
194       // Check whether is a white space.
195       const Character character = *( parameters.textBuffer + characterFirstIndex );
196       const bool isWhiteSpace = TextAbstraction::IsWhiteSpace( character );
197
198       // Increase the accumulated length.
199       if( isWhiteSpace )
200       {
201         // Add the length to the length of white spaces at the end of the line.
202         tmpLineLayout.wsLengthEndOfLine += glyphInfo.advance; // I use the advance as the width is always zero for the white spaces.
203         tmpLineLayout.widthAdvanceDiff = 0.f;
204       }
205       else
206       {
207         // Add as well any previous white space length.
208         tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine + glyphInfo.advance;
209         tmpLineLayout.widthAdvanceDiff = glyphInfo.width - glyphInfo.advance;
210
211         // Clear the white space length at the end of the line.
212         tmpLineLayout.wsLengthEndOfLine = 0.f;
213       }
214
215       // Check if the accumulated length fits in the width of the box.
216       if( lineLayout.length + tmpLineLayout.length + tmpLineLayout.widthAdvanceDiff + ( ( 0.f < tmpLineLayout.length ) ? lineLayout.wsLengthEndOfLine : 0.f ) > parameters.boundingBox.width )
217       {
218         // Current word does not fit in the box's width.
219         return;
220       }
221
222       if( TextAbstraction::LINE_MUST_BREAK == lineBreakInfo )
223       {
224         // Must break the line. Update the line layout and return.
225         lineLayout.numberOfCharacters += tmpLineLayout.numberOfCharacters;
226         lineLayout.numberOfGlyphs += tmpLineLayout.numberOfGlyphs;
227         lineLayout.length += tmpLineLayout.length;
228         lineLayout.widthAdvanceDiff = tmpLineLayout.widthAdvanceDiff;
229
230         if( 0.f < tmpLineLayout.length )
231         {
232           lineLayout.length += lineLayout.wsLengthEndOfLine;
233
234           lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
235         }
236         else
237         {
238           lineLayout.wsLengthEndOfLine += tmpLineLayout.wsLengthEndOfLine;
239         }
240
241         if( tmpLineLayout.ascender > lineLayout.ascender )
242         {
243           lineLayout.ascender = tmpLineLayout.ascender;
244         }
245
246         if( tmpLineLayout.descender > lineLayout.descender )
247         {
248           lineLayout.descender = tmpLineLayout.descender;
249         }
250
251         tmpLineLayout.numberOfCharacters = 0u;
252         tmpLineLayout.numberOfGlyphs = 0u;
253         tmpLineLayout.length = 0u;
254         tmpLineLayout.widthAdvanceDiff = 0u;
255         tmpLineLayout.wsLengthEndOfLine = 0u;
256         tmpLineLayout.ascender = 0.f;
257         tmpLineLayout.descender = 0.f;
258         return;
259       }
260
261       if( TextAbstraction::WORD_BREAK == wordBreakInfo )
262       {
263         // Current glyph is the last one of the current word.
264         // Add the temporal layout to the current one.
265         lineLayout.numberOfCharacters += tmpLineLayout.numberOfCharacters;
266         lineLayout.numberOfGlyphs += tmpLineLayout.numberOfGlyphs;
267         lineLayout.length += tmpLineLayout.length;
268         lineLayout.widthAdvanceDiff = tmpLineLayout.widthAdvanceDiff;
269
270         if( 0.f < tmpLineLayout.length )
271         {
272           lineLayout.length += lineLayout.wsLengthEndOfLine;
273
274           lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
275         }
276         else
277         {
278           lineLayout.wsLengthEndOfLine += tmpLineLayout.wsLengthEndOfLine;
279         }
280
281         if( tmpLineLayout.ascender > lineLayout.ascender )
282         {
283           lineLayout.ascender = tmpLineLayout.ascender;
284         }
285
286         if( tmpLineLayout.descender > lineLayout.descender )
287         {
288           lineLayout.descender = tmpLineLayout.descender;
289         }
290
291         tmpLineLayout.numberOfCharacters = 0u;
292         tmpLineLayout.numberOfGlyphs = 0u;
293         tmpLineLayout.length = 0u;
294         tmpLineLayout.widthAdvanceDiff = 0u;
295         tmpLineLayout.wsLengthEndOfLine = 0u;
296         tmpLineLayout.ascender = 0.f;
297         tmpLineLayout.descender = 0.f;
298       }
299
300       if( lastFontId != glyphInfo.fontId )
301       {
302         Text::FontMetrics fontMetrics;
303         mFontClient.GetFontMetrics( glyphInfo.fontId, fontMetrics );
304
305         // Sets the maximum ascender.
306         if( fontMetrics.ascender > tmpLineLayout.ascender )
307         {
308           tmpLineLayout.ascender = fontMetrics.ascender;
309         }
310
311         // Sets the maximum descender.
312         if( -fontMetrics.descender > tmpLineLayout.descender )
313         {
314           tmpLineLayout.descender = -fontMetrics.descender;
315         }
316
317         lastFontId = glyphInfo.fontId;
318       }
319     }
320   }
321
322   bool LayoutText( const LayoutParameters& layoutParameters,
323                    Vector<Vector2>& glyphPositions,
324                    Vector<LineRun>& lines,
325                    Size& actualSize )
326   {
327     // TODO Switch between different layouts
328     bool update = false;
329
330     switch( mLayout )
331     {
332       case LayoutEngine::SINGLE_LINE_BOX:
333       {
334         update = SingleLineLayout( layoutParameters,
335                                    glyphPositions,
336                                    lines,
337                                    actualSize );
338         break;
339       }
340       case LayoutEngine::MULTI_LINE_BOX:
341       {
342         update = MultiLineLayout( layoutParameters,
343                                   glyphPositions,
344                                   lines,
345                                   actualSize );
346         break;
347       }
348       default:
349         break;
350     }
351
352     return update;
353   }
354
355   void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters,
356                                  Vector<Vector2>& glyphPositions )
357   {
358     for( LineIndex lineIndex = 0u; lineIndex < layoutParameters.numberOfBidirectionalInfoRuns; ++lineIndex )
359     {
360       const BidirectionalLineInfoRun& bidiLine = *( layoutParameters.lineBidirectionalInfoRunsBuffer +lineIndex  );
361
362       float penX = 0.f;
363
364       Vector2* glyphPositionsBuffer = glyphPositions.Begin();
365
366       for( CharacterIndex characterLogicalIndex = 0u;
367            characterLogicalIndex < bidiLine.characterRun.numberOfCharacters;
368            ++characterLogicalIndex )
369       {
370         // Convert the character in the logical order into the character in the visual order.
371         const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *( bidiLine.visualToLogicalMap + characterLogicalIndex );
372
373         // Get the number of glyphs of the character.
374         const Length numberOfGlyphs = *( layoutParameters.glyphsPerCharacterBuffer + characterVisualIndex );
375
376         for( GlyphIndex index = 0u; index < numberOfGlyphs; ++index )
377         {
378           // Convert the character in the visual order into the glyph in the visual order.
379           GlyphIndex glyphIndex = 1u + *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex + index ) - numberOfGlyphs;
380
381           const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + glyphIndex );
382           Vector2& position = *( glyphPositionsBuffer + glyphIndex );
383
384           position.x = penX + glyph.xBearing;
385           penX += glyph.advance;
386         }
387       }
388     }
389   }
390
391   void Align( const LayoutParameters& layoutParameters,
392               const Size& layoutSize,
393               const Vector<LineRun>& lines,
394               Vector<Vector2>& glyphPositions )
395   {
396     Vector2* glyphPositionsBuffer = glyphPositions.Begin();
397
398     // Traverse all lines and align the glyphs.
399     // LayoutParameters contains bidirectional info for those lines with
400     // right to left text, this info includes the paragraph's direction.
401
402     LineIndex bidiLineIndex = 0u;
403     for( Vector<LineRun>::ConstIterator it = lines.Begin(), endIt = lines.End();
404          it != endIt;
405          ++it )
406     {
407       const LineRun& line = *it;
408
409       // 1) Get the paragrap's direction.
410       bool paragraphDirection = false;
411
412       // Check if there is any right to left line.
413       if( ( NULL != layoutParameters.lineBidirectionalInfoRunsBuffer ) &&
414           ( bidiLineIndex < layoutParameters.numberOfBidirectionalInfoRuns ) )
415       {
416         const BidirectionalLineInfoRun* bidiLine = layoutParameters.lineBidirectionalInfoRunsBuffer + bidiLineIndex;
417
418         // Get the right to left line that match with current line.
419         while( ( line.characterRun.characterIndex > bidiLine->characterRun.characterIndex ) &&
420                ( bidiLineIndex < layoutParameters.numberOfBidirectionalInfoRuns ) )
421         {
422           ++bidiLineIndex;
423           bidiLine = layoutParameters.lineBidirectionalInfoRunsBuffer + bidiLineIndex;
424         }
425
426         if( line.characterRun.characterIndex == bidiLine->characterRun.characterIndex )
427         {
428           paragraphDirection = bidiLine->direction;
429         }
430       }
431
432       // 2) Calculate the alignment offset accordingly with the align option,
433       //    the box width, line length, and the paragraphs direction.
434       float alignOffset = CalculateAlignment( layoutSize.width,
435                                               line.lineSize.width,
436                                               line.extraLength,
437                                               paragraphDirection );
438
439       // 3) Traverse all glyphs and update the 'x' position.
440       for( GlyphIndex index = line.glyphIndex,
441              endIndex = line.glyphIndex + line.numberOfGlyphs;
442            index < endIndex;
443            ++index )
444       {
445         Vector2& position = *( glyphPositionsBuffer + index );
446
447         position.x += alignOffset;
448       }
449     }
450   }
451
452   bool SingleLineLayout( const LayoutParameters& layoutParameters,
453                          Vector<Vector2>& glyphPositions,
454                          Vector<LineRun>& lines,
455                          Size& actualSize )
456   {
457     LineLayout layout;
458     layout.glyphIndex = 0u;
459     GetLineLayoutForBox( layoutParameters,
460                          layout );
461
462     // Create a line run and add it to the lines.
463     const GlyphIndex lastGlyphIndex = layoutParameters.totalNumberOfGlyphs - 1u;
464
465     LineRun lineRun;
466     lineRun.glyphIndex = 0u;
467     lineRun.numberOfGlyphs = layoutParameters.totalNumberOfGlyphs;
468     lineRun.characterRun.characterIndex = 0u;
469     lineRun.characterRun.numberOfCharacters = *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex );
470     lineRun.lineSize.width = layout.length;
471     lineRun.lineSize.height = layout.ascender + layout.descender;
472     lineRun.extraLength = layout.wsLengthEndOfLine;
473
474     lines.PushBack( lineRun );
475
476     // Update the actual size.
477     actualSize.width = layout.length;
478     actualSize.height = lineRun.lineSize.height;
479
480     float penX = 0.f;
481     float penY = layout.ascender;
482
483     Vector2* glyphPositionsBuffer = glyphPositions.Begin();
484     for( GlyphIndex glyphIndex = 0u; glyphIndex < layout.numberOfGlyphs; ++glyphIndex )
485     {
486       const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + glyphIndex );
487       Vector2& position = *( glyphPositionsBuffer + glyphIndex );
488
489       position.x = penX + glyph.xBearing;
490       position.y = penY - glyph.yBearing;
491
492       penX += glyph.advance;
493     }
494
495     return true;
496   }
497
498   bool MultiLineLayout( const LayoutParameters& layoutParameters,
499                         Vector<Vector2>& glyphPositions,
500                         Vector<LineRun>& lines,
501                         Size& actualSize )
502   {
503     float penY = 0.f;
504     for( GlyphIndex index = 0u; index < layoutParameters.totalNumberOfGlyphs; )
505     {
506       float penX = 0.f;
507
508       // Get the layout for the line.
509       LineLayout layout;
510       layout.glyphIndex = index;
511       GetMultiLineLayoutForBox( layoutParameters,
512                                 layout );
513
514       if( 0u == layout.numberOfGlyphs )
515       {
516         // The width is too small and no characters are laid-out.
517         return false;
518       }
519
520       // Create a line run and add it to the lines.
521       const GlyphIndex lastGlyphIndex = index + layout.numberOfGlyphs - 1u;
522
523       LineRun lineRun;
524       lineRun.glyphIndex = index;
525       lineRun.numberOfGlyphs = layout.numberOfGlyphs;
526       lineRun.characterRun.characterIndex = *( layoutParameters.glyphsToCharactersBuffer + index );
527       lineRun.characterRun.numberOfCharacters = ( *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex ) ) - lineRun.characterRun.characterIndex;
528       lineRun.lineSize.width = layout.length + ( ( layout.widthAdvanceDiff > 0.f ) ? layout.widthAdvanceDiff : 0.f );
529       lineRun.lineSize.height = layout.ascender + layout.descender;
530       lineRun.extraLength = layout.wsLengthEndOfLine;
531
532       lines.PushBack( lineRun );
533
534       // Update the actual size.
535       if( layout.length + layout.widthAdvanceDiff > actualSize.width )
536       {
537         actualSize.width = layout.length;
538       }
539
540       actualSize.height += lineRun.lineSize.height;
541
542       // Traverse the glyphs and set the positions.
543
544       penY += layout.ascender;
545
546       Vector2* glyphPositionsBuffer = glyphPositions.Begin();
547       for( GlyphIndex i = index; i < index + layout.numberOfGlyphs; ++i )
548       {
549         const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + i );
550         Vector2& position = *( glyphPositionsBuffer + i );
551
552         position.x = penX + glyph.xBearing;
553         position.y = penY - glyph.yBearing;
554
555         penX += glyph.advance;
556       }
557
558       penY += layout.descender;
559
560       // Increase the glyph index.
561       index += layout.numberOfGlyphs;
562     }
563
564     return true;
565   }
566
567   float CalculateAlignment( float boxWidth,
568                             float lineLength,
569                             float extraLength,
570                             bool paragraphDirection )
571   {
572     float offset = 0.f;
573
574     Alignment alignment = mAlignment;
575     if( paragraphDirection &&
576         ( ALIGN_CENTER != alignment ) )
577     {
578       if( ALIGN_BEGIN == alignment )
579       {
580         alignment = ALIGN_END;
581       }
582       else
583       {
584         alignment = ALIGN_BEGIN;
585       }
586     }
587
588     switch( alignment )
589     {
590       case ALIGN_BEGIN:
591       {
592         offset = 0.f;
593         break;
594       }
595       case ALIGN_CENTER:
596       {
597         offset = 0.5f * ( boxWidth - lineLength );
598         const int intOffset = static_cast<int>( offset ); // try to avoid pixel alignment.
599         offset = static_cast<float>( intOffset );
600         break;
601       }
602       case ALIGN_END:
603       {
604         offset = boxWidth - lineLength;
605         break;
606       }
607     }
608
609     if( paragraphDirection )
610     {
611       offset -= extraLength;
612     }
613
614     return offset;
615   }
616
617   LayoutEngine::Layout mLayout;
618   LayoutEngine::Alignment mAlignment;
619
620   TextAbstraction::FontClient mFontClient;
621 };
622
623 LayoutEngine::LayoutEngine()
624 : mImpl( NULL )
625 {
626   mImpl = new LayoutEngine::Impl();
627 }
628
629 LayoutEngine::~LayoutEngine()
630 {
631   delete mImpl;
632 }
633
634 void LayoutEngine::SetLayout( Layout layout )
635 {
636   mImpl->mLayout = layout;
637 }
638
639 unsigned int LayoutEngine::GetLayout() const
640 {
641   return mImpl->mLayout;
642 }
643
644 void LayoutEngine::SetAlignment( Alignment alignment )
645 {
646   mImpl->mAlignment = alignment;
647 }
648
649 LayoutEngine::Alignment LayoutEngine::GetAlignment() const
650 {
651   return mImpl->mAlignment;
652 }
653
654 bool LayoutEngine::LayoutText( const LayoutParameters& layoutParameters,
655                                Vector<Vector2>& glyphPositions,
656                                Vector<LineRun>& lines,
657                                Size& actualSize )
658 {
659   return mImpl->LayoutText( layoutParameters,
660                             glyphPositions,
661                             lines,
662                             actualSize );
663 }
664
665 void LayoutEngine::ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters,
666                                              Vector<Vector2>& glyphPositions )
667 {
668   mImpl->ReLayoutRightToLeftLines( layoutParameters,
669                                    glyphPositions );
670 }
671
672 void LayoutEngine::Align( const LayoutParameters& layoutParameters,
673                           const Size& layoutSize,
674                           const Vector<LineRun>& lines,
675                           Vector<Vector2>& glyphPositions )
676 {
677   mImpl->Align( layoutParameters,
678                 layoutSize,
679                 lines,
680                 glyphPositions );
681 }
682
683 } // namespace Text
684
685 } // namespace Toolkit
686
687 } // namespace Dali