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