Save the previous character's extra width
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / layouts / layout-engine.cpp
index 8816e33..af257ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
+#include <dali-toolkit/internal/text/cursor-helper-functions.h>
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
 
@@ -37,6 +38,9 @@ namespace Toolkit
 namespace Text
 {
 
+namespace Layout
+{
+
 namespace
 {
 
@@ -47,26 +51,7 @@ namespace
 const float MAX_FLOAT = std::numeric_limits<float>::max();
 const bool RTL = true;
 const float CURSOR_WIDTH = 1.f;
-
-Length CountParagraphs( const LayoutParameters& layoutParameters )
-{
-  Length numberOfParagraphs = 0u;
-
-  const CharacterIndex startCharacterIndex = *( layoutParameters.glyphsToCharactersBuffer + layoutParameters.startGlyphIndex );
-
-  const GlyphIndex lastGlyphIndex = layoutParameters.startGlyphIndex + layoutParameters.numberOfGlyphs - 1u;
-  const CharacterIndex lastCharacterIndexPlusOne = *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex );
-
-  for( CharacterIndex index = startCharacterIndex; index < lastCharacterIndexPlusOne; ++index )
-  {
-    if( TextAbstraction::LINE_MUST_BREAK == *( layoutParameters.lineBreakInfoBuffer + index ) )
-    {
-      ++numberOfParagraphs;
-    }
-  }
-
-  return numberOfParagraphs;
-}
+const float LINE_SPACING= 0.f;
 
 } //namespace
 
@@ -85,7 +70,8 @@ struct LineLayout
     extraWidth( 0.f ),
     wsLengthEndOfLine( 0.f ),
     ascender( 0.f ),
-    descender( MAX_FLOAT )
+    descender( MAX_FLOAT ),
+    lineSpacing( 0.f )
   {}
 
   ~LineLayout()
@@ -115,16 +101,16 @@ struct LineLayout
   float          wsLengthEndOfLine;  ///< The length of the white spaces at the end of the line.
   float          ascender;           ///< The maximum ascender of all fonts in the line.
   float          descender;          ///< The minimum descender of all fonts in the line.
+  float          lineSpacing;        ///< The line spacing
 };
 
-struct LayoutEngine::Impl
+struct Engine::Impl
 {
   Impl()
-  : mLayout( LayoutEngine::SINGLE_LINE_BOX ),
-    mHorizontalAlignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN ),
-    mVerticalAlignment( LayoutEngine::VERTICAL_ALIGN_TOP ),
+  : mLayout( Layout::Engine::SINGLE_LINE_BOX ),
     mCursorWidth( CURSOR_WIDTH ),
-    mEllipsisEnabled( false )
+    mDefaultLineSpacing( LINE_SPACING ),
+    mPreviousCharacterExtraWidth( 0.0f )
   {
   }
 
@@ -150,6 +136,9 @@ struct LayoutEngine::Impl
     {
       lineLayout.descender = fontMetrics.descender;
     }
+
+    // set the line spacing
+    lineLayout.lineSpacing = mDefaultLineSpacing;
   }
 
   /**
@@ -204,7 +193,7 @@ struct LayoutEngine::Impl
    * @param[in,out] paragraphDirection in: the current paragraph's direction, out: the next paragraph's direction. Is set after a must break.
    * @param[in] completelyFill Whether to completely fill the line ( even if the last word exceeds the boundaries ).
    */
-  void GetLineLayoutForBox( const LayoutParameters& parameters,
+  void GetLineLayoutForBox( const Parameters& parameters,
                             LineLayout& lineLayout,
                             CharacterDirection& paragraphDirection,
                             bool completelyFill )
@@ -215,6 +204,7 @@ struct LayoutEngine::Impl
     LineLayout tmpLineLayout;
 
     const bool isMultiline = mLayout == MULTI_LINE_BOX;
+    const bool isWordLaidOut = parameters.lineWrapMode == Text::LineWrap::WORD;
 
     // The last glyph to be laid-out.
     const GlyphIndex lastGlyphOfParagraphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs;
@@ -356,6 +346,7 @@ struct LayoutEngine::Impl
 
             const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
             tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+            tmpExtraWidth = std::max( mPreviousCharacterExtraWidth - glyphMetrics.advance, tmpExtraWidth );
           }
         }
         else
@@ -369,6 +360,7 @@ struct LayoutEngine::Impl
 
               const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
               tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+              tmpExtraWidth = std::max( mPreviousCharacterExtraWidth - glyphMetrics.advance, tmpExtraWidth );
             }
             else // LTR
             {
@@ -396,6 +388,7 @@ struct LayoutEngine::Impl
 
               const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
               tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+              tmpExtraWidth = std::max( mPreviousCharacterExtraWidth - glyphMetrics.advance, tmpExtraWidth );
             }
           }
         }
@@ -404,6 +397,9 @@ struct LayoutEngine::Impl
         tmpLineLayout.wsLengthEndOfLine = 0.f;
       }
 
+      // Save the current extra width to compare with the next one
+      mPreviousCharacterExtraWidth = tmpExtraWidth;
+
       // Check if the accumulated length fits in the width of the box.
       if( ( completelyFill || isMultiline ) && !isWhiteSpace &&
           ( tmpExtraBearing + lineLayout.length + lineLayout.wsLengthEndOfLine + tmpLineLayout.length + tmpExtraWidth > parameters.boundingBox.width ) )
@@ -464,7 +460,7 @@ struct LayoutEngine::Impl
       if( isMultiline &&
           ( TextAbstraction::WORD_BREAK == wordBreakInfo ) )
       {
-        oneWordLaidOut = true;
+        oneWordLaidOut = isWordLaidOut;
         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  One word laid-out\n" );
 
         // Current glyph is the last one of the current word.
@@ -484,37 +480,9 @@ struct LayoutEngine::Impl
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
   }
 
-  /**
-   * @brief Calculates the vertical offset to add to the new laid-out glyphs.
-   *
-   * @pre @p lineIndex must be between 0 and the number of lines (both inclusive).
-   *
-   * @param[in] lines The previously laid-out lines.
-   * @param[in] lineIndex Index to the line where the new laid-out lines are inserted.
-   *
-   * @return The vertical offset of the lines starting from the beginning to the line @p lineIndex.
-   */
-  float SetParagraphOffset( const Vector<LineRun>& lines,
-                            LineIndex lineIndex )
-  {
-    float offset = 0.f;
-
-    for( Vector<LineRun>::ConstIterator it = lines.Begin(),
-           endIt = lines.Begin() + lineIndex;
-         it != endIt;
-         ++it )
-    {
-      const LineRun& line = *it;
-
-      offset += line.ascender + -line.descender;
-    }
-
-    return offset;
-  }
-
   void SetGlyphPositions( const GlyphInfo* const glyphsBuffer,
                           Length numberOfGlyphs,
-                          float penY,
+                          float outlineWidth,
                           Vector2* glyphPositionsBuffer )
   {
     // Traverse the glyphs and set the positions.
@@ -524,7 +492,8 @@ struct LayoutEngine::Impl
     // so the penX position needs to be moved to the right.
 
     const GlyphInfo& glyph = *glyphsBuffer;
-    float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing : 0.f;
+    float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing + outlineWidth : outlineWidth;
+
 
     for( GlyphIndex i = 0u; i < numberOfGlyphs; ++i )
     {
@@ -532,7 +501,7 @@ struct LayoutEngine::Impl
       Vector2& position = *( glyphPositionsBuffer + i );
 
       position.x = penX + glyph.xBearing;
-      position.y = penY - glyph.yBearing;
+      position.y = -glyph.yBearing;
 
       penX += glyph.advance;
     }
@@ -584,7 +553,7 @@ struct LayoutEngine::Impl
    *
    * return Whether the line is ellipsized.
    */
-  bool EllipsisLine( const LayoutParameters& layoutParameters,
+  bool EllipsisLine( const Parameters& layoutParameters,
                      const LineLayout& layout,
                      Size& layoutSize,
                      LineRun* linesBuffer,
@@ -611,7 +580,7 @@ struct LayoutEngine::Impl
         // Get the last line and layout it again with the 'completelyFill' flag to true.
         lineRun = linesBuffer + ( numberOfLines - 1u );
 
-        penY -= layout.ascender - lineRun->descender;
+        penY -= layout.ascender - lineRun->descender + lineRun->lineSpacing;
 
         ellipsisLayout.glyphIndex = lineRun->glyphRun.glyphIndex;
       }
@@ -642,11 +611,14 @@ struct LayoutEngine::Impl
       lineRun->ellipsis = true;
 
       layoutSize.width = layoutParameters.boundingBox.width;
-      layoutSize.height += ( lineRun->ascender + -lineRun->descender );
+      if( layoutSize.height < Math::MACHINE_EPSILON_1000 )
+      {
+        layoutSize.height += ( lineRun->ascender + -lineRun->descender ) + lineRun->lineSpacing;
+      }
 
       SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun->glyphRun.glyphIndex,
                          ellipsisLayout.numberOfGlyphs,
-                         penY,
+                         layoutParameters.outlineWidth,
                          glyphPositionsBuffer + lineRun->glyphRun.glyphIndex - layoutParameters.startGlyphIndex );
     }
 
@@ -664,7 +636,7 @@ struct LayoutEngine::Impl
    * @param[in,out] numberOfLines The number of laid-out lines.
    * @param[in] isLastLine Whether the laid-out line is the last one.
    */
-  void UpdateTextLayout( const LayoutParameters& layoutParameters,
+  void UpdateTextLayout( const Parameters& layoutParameters,
                          const LineLayout& layout,
                          Size& layoutSize,
                          LineRun* linesBuffer,
@@ -679,6 +651,8 @@ struct LayoutEngine::Impl
     lineRun.glyphRun.numberOfGlyphs = layout.numberOfGlyphs;
     lineRun.characterRun.characterIndex = layout.characterIndex;
     lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters;
+    lineRun.lineSpacing = mDefaultLineSpacing;
+
     if( isLastLine && !layoutParameters.isLastNewParagraph )
     {
       const float width = layout.extraBearing + layout.length + layout.extraWidth + layout.wsLengthEndOfLine;
@@ -709,24 +683,24 @@ struct LayoutEngine::Impl
       layoutSize.width = lineRun.width;
     }
 
-    layoutSize.height += ( lineRun.ascender + -lineRun.descender );
+    layoutSize.height += ( lineRun.ascender + -lineRun.descender ) + lineRun.lineSpacing;
   }
 
   /**
    * @brief Updates the text layout with the last laid-out line.
    *
    * @param[in] layoutParameters The parameters needed to layout the text.
-   * @param[in] layout The line layout.
+   * @param[in] characterIndex The character index of the line.
+   * @param[in] glyphIndex The glyph index of the line.
    * @param[in,out] layoutSize The text's layout size.
    * @param[in,out] linesBuffer Pointer to the line's buffer.
-   * @param[in] index Index to the vector of glyphs.
    * @param[in,out] numberOfLines The number of laid-out lines.
    */
-  void UpdateTextLayout( const LayoutParameters& layoutParameters,
-                         const LineLayout& layout,
+  void UpdateTextLayout( const Parameters& layoutParameters,
+                         CharacterIndex characterIndex,
+                         GlyphIndex glyphIndex,
                          Size& layoutSize,
                          LineRun* linesBuffer,
-                         GlyphIndex index,
                          Length& numberOfLines )
   {
     // Need to add a new line with no characters but with height to increase the layoutSize.height
@@ -738,9 +712,9 @@ struct LayoutEngine::Impl
     LineRun& lineRun = *( linesBuffer + numberOfLines );
     ++numberOfLines;
 
-    lineRun.glyphRun.glyphIndex = index + layout.numberOfGlyphs;
+    lineRun.glyphRun.glyphIndex = glyphIndex;
     lineRun.glyphRun.numberOfGlyphs = 0u;
-    lineRun.characterRun.characterIndex = layout.characterIndex + layout.numberOfCharacters;
+    lineRun.characterRun.characterIndex = characterIndex;
     lineRun.characterRun.numberOfCharacters = 0u;
     lineRun.width = 0.f;
     lineRun.ascender = fontMetrics.ascender;
@@ -749,8 +723,9 @@ struct LayoutEngine::Impl
     lineRun.alignmentOffset = 0.f;
     lineRun.direction = !RTL;
     lineRun.ellipsis = false;
+    lineRun.lineSpacing = mDefaultLineSpacing;
 
-    layoutSize.height += ( lineRun.ascender + -lineRun.descender );
+    layoutSize.height += ( lineRun.ascender + -lineRun.descender ) + lineRun.lineSpacing;
   }
 
   /**
@@ -774,7 +749,7 @@ struct LayoutEngine::Impl
         layoutSize.width = line.width;
       }
 
-      layoutSize.height += ( line.ascender + -line.descender );
+      layoutSize.height += ( line.ascender + -line.descender ) + line.lineSpacing;
     }
   }
 
@@ -786,7 +761,7 @@ struct LayoutEngine::Impl
    * @param[in] characterOffset The offset to be added to the runs of characters.
    * @param[in] glyphOffset The offset to be added to the runs of glyphs.
    */
-  void UpdateLineIndexOffsets( const LayoutParameters& layoutParameters,
+  void UpdateLineIndexOffsets( const Parameters& layoutParameters,
                                Vector<LineRun>& lines,
                                Length characterOffset,
                                Length glyphOffset )
@@ -807,20 +782,65 @@ struct LayoutEngine::Impl
     }
   }
 
-  bool LayoutText( const LayoutParameters& layoutParameters,
+  bool LayoutText( const Parameters& layoutParameters,
                    Vector<Vector2>& glyphPositions,
                    Vector<LineRun>& lines,
-                   Size& layoutSize )
+                   Size& layoutSize,
+                   bool elideTextEnabled )
   {
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->LayoutText\n" );
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  box size %f, %f\n", layoutParameters.boundingBox.width, layoutParameters.boundingBox.height );
 
     if( 0u == layoutParameters.numberOfGlyphs )
     {
-      // Nothing to do if there are no glyphs to layout.
+      // Add an extra line if the last character is a new paragraph character and the last line doesn't have zero characters.
+      if( layoutParameters.isLastNewParagraph )
+      {
+        Length numberOfLines = lines.Count();
+        if( 0u != numberOfLines )
+        {
+          const LineRun& lastLine = *( lines.End() - 1u );
+
+          if( 0u != lastLine.characterRun.numberOfCharacters )
+          {
+            // Need to add a new line with no characters but with height to increase the layoutSize.height
+            LineRun newLine;
+            Initialize( newLine );
+            lines.PushBack( newLine );
+
+            UpdateTextLayout( layoutParameters,
+                              lastLine.characterRun.characterIndex + lastLine.characterRun.numberOfCharacters,
+                              lastLine.glyphRun.glyphIndex + lastLine.glyphRun.numberOfGlyphs,
+                              layoutSize,
+                              lines.Begin(),
+                              numberOfLines );
+          }
+        }
+      }
+
+      // Calculates the layout size.
+      UpdateLayoutSize( lines,
+                        layoutSize );
+
+      // Nothing else do if there are no glyphs to layout.
       return false;
     }
 
+    const GlyphIndex lastGlyphPlusOne = layoutParameters.startGlyphIndex + layoutParameters.numberOfGlyphs;
+
+    // In a previous layout, an extra line with no characters may have been added if the text ended with a new paragraph character.
+    // This extra line needs to be removed.
+    if( 0u != lines.Count() )
+    {
+      Vector<LineRun>::Iterator lastLine = lines.End() - 1u;
+
+      if( ( 0u == lastLine->characterRun.numberOfCharacters ) &&
+          ( lastGlyphPlusOne == layoutParameters.totalNumberOfGlyphs ) )
+      {
+        lines.Remove( lastLine );
+      }
+    }
+
     // Set the first paragraph's direction.
     CharacterDirection paragraphDirection = ( NULL != layoutParameters.characterDirectionBuffer ) ? *layoutParameters.characterDirectionBuffer : !RTL;
 
@@ -834,8 +854,7 @@ struct LayoutEngine::Impl
     Vector<LineRun> newLines;
 
     // Estimate the number of lines.
-    // TODO: In a next patch the paragraphs are properly managed and this can be removed.
-    Length linesCapacity = CountParagraphs( layoutParameters );
+    Length linesCapacity = std::max( 1u, layoutParameters.estimatedNumberOfLines );
     Length numberOfLines = 0u;
 
     if( updateCurrentBuffer )
@@ -854,10 +873,9 @@ struct LayoutEngine::Impl
       linesBuffer = lines.Begin();
     }
 
-    float penY = SetParagraphOffset( lines,
-                                     layoutParameters.startLineIndex );
+    float penY = CalculateLineOffset( lines,
+                                      layoutParameters.startLineIndex );
 
-    const GlyphIndex lastGlyphPlusOne = layoutParameters.startGlyphIndex + layoutParameters.numberOfGlyphs;
     for( GlyphIndex index = layoutParameters.startGlyphIndex; index < lastGlyphPlusOne; )
     {
       CharacterDirection currentParagraphDirection = paragraphDirection;
@@ -892,7 +910,7 @@ struct LayoutEngine::Impl
       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  pen y %f\n", penY );
 
       bool ellipsis = false;
-      if( mEllipsisEnabled )
+      if( elideTextEnabled )
       {
         // Does the ellipsis of the last line.
         ellipsis = EllipsisLine( layoutParameters,
@@ -933,7 +951,9 @@ struct LayoutEngine::Impl
                           numberOfLines,
                           isLastLine );
 
-        if( isLastLine &&
+        const GlyphIndex nextIndex = index + layout.numberOfGlyphs;
+
+        if( ( nextIndex == layoutParameters.totalNumberOfGlyphs ) &&
             layoutParameters.isLastNewParagraph &&
             ( mLayout == MULTI_LINE_BOX ) )
         {
@@ -951,25 +971,24 @@ struct LayoutEngine::Impl
           }
 
           UpdateTextLayout( layoutParameters,
-                            layout,
+                            layout.characterIndex + layout.numberOfCharacters,
+                            index + layout.numberOfGlyphs,
                             layoutSize,
                             linesBuffer,
-                            index,
                             numberOfLines );
         } // whether to add a last line.
 
         // Sets the positions of the glyphs.
         SetGlyphPositions( layoutParameters.glyphsBuffer + index,
                            layout.numberOfGlyphs,
-                           penY,
+                           layoutParameters.outlineWidth,
                            glyphPositionsBuffer + index - layoutParameters.startGlyphIndex );
 
         // Updates the vertical pen's position.
-        penY += -layout.descender;
+        penY += -layout.descender + layout.lineSpacing + mDefaultLineSpacing;
 
         // Increase the glyph index.
-        index += layout.numberOfGlyphs;
-
+        index = nextIndex;
       } // no ellipsis
     } // end for() traversing glyphs.
 
@@ -978,6 +997,7 @@ struct LayoutEngine::Impl
       glyphPositions.Insert( glyphPositions.Begin() + layoutParameters.startGlyphIndex,
                              newGlyphPositions.Begin(),
                              newGlyphPositions.End() );
+      glyphPositions.Resize( layoutParameters.totalNumberOfGlyphs );
 
       newLines.Resize( numberOfLines );
 
@@ -1015,7 +1035,7 @@ struct LayoutEngine::Impl
     return true;
   }
 
-  void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters,
+  void ReLayoutRightToLeftLines( const Parameters& layoutParameters,
                                  CharacterIndex startIndex,
                                  Length numberOfCharacters,
                                  Vector<Vector2>& glyphPositions )
@@ -1042,7 +1062,7 @@ struct LayoutEngine::Impl
       const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *bidiLine.visualToLogicalMap;
       const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex ) );
 
-      float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing : 0.f;
+      float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing - layoutParameters.outlineWidth : -layoutParameters.outlineWidth;
 
       Vector2* glyphPositionsBuffer = glyphPositions.Begin();
 
@@ -1077,10 +1097,13 @@ struct LayoutEngine::Impl
   void Align( const Size& size,
               CharacterIndex startIndex,
               Length numberOfCharacters,
-              Vector<LineRun>& lines )
+              Text::HorizontalAlignment::Type horizontalAlignment,
+              Vector<LineRun>& lines,
+              float& alignmentOffset )
   {
     const CharacterIndex lastCharacterPlusOne = startIndex + numberOfCharacters;
 
+    alignmentOffset = MAX_FLOAT;
     // Traverse all lines and align the glyphs.
     for( Vector<LineRun>::Iterator it = lines.Begin(), endIt = lines.End();
          it != endIt;
@@ -1103,36 +1126,41 @@ struct LayoutEngine::Impl
       // Calculate the line's alignment offset accordingly with the align option,
       // the box width, line length, and the paragraph's direction.
       CalculateHorizontalAlignment( size.width,
+                                    horizontalAlignment,
                                     line );
+
+      // Updates the alignment offset.
+      alignmentOffset = std::min( alignmentOffset, line.alignmentOffset );
     }
   }
 
   void CalculateHorizontalAlignment( float boxWidth,
+                                     HorizontalAlignment::Type horizontalAlignment,
                                      LineRun& line )
   {
     line.alignmentOffset = 0.f;
     const bool isRTL = RTL == line.direction;
     float lineLength = line.width;
 
-    HorizontalAlignment alignment = mHorizontalAlignment;
+    HorizontalAlignment::Type alignment = horizontalAlignment;
     if( isRTL )
     {
       // Swap the alignment type if the line is right to left.
       switch( alignment )
       {
-        case HORIZONTAL_ALIGN_BEGIN:
+        case HorizontalAlignment::BEGIN:
         {
-          alignment = HORIZONTAL_ALIGN_END;
+          alignment = HorizontalAlignment::END;
           break;
         }
-        case HORIZONTAL_ALIGN_CENTER:
+        case HorizontalAlignment::CENTER:
         {
           // Nothing to do.
           break;
         }
-        case HORIZONTAL_ALIGN_END:
+        case HorizontalAlignment::END:
         {
-          alignment = HORIZONTAL_ALIGN_BEGIN;
+          alignment = HorizontalAlignment::BEGIN;
           break;
         }
       }
@@ -1141,7 +1169,7 @@ struct LayoutEngine::Impl
     // Calculate the horizontal line offset.
     switch( alignment )
     {
-      case HORIZONTAL_ALIGN_BEGIN:
+      case HorizontalAlignment::BEGIN:
       {
         line.alignmentOffset = 0.f;
 
@@ -1152,7 +1180,7 @@ struct LayoutEngine::Impl
         }
         break;
       }
-      case HORIZONTAL_ALIGN_CENTER:
+      case HorizontalAlignment::CENTER:
       {
         line.alignmentOffset = 0.5f * ( boxWidth - lineLength );
 
@@ -1164,7 +1192,7 @@ struct LayoutEngine::Impl
         line.alignmentOffset = floorf( line.alignmentOffset ); // try to avoid pixel alignment.
         break;
       }
-      case HORIZONTAL_ALIGN_END:
+      case HorizontalAlignment::END:
       {
         if( isRTL )
         {
@@ -1177,97 +1205,84 @@ struct LayoutEngine::Impl
     }
   }
 
-  LayoutEngine::Layout mLayout;
-  LayoutEngine::HorizontalAlignment mHorizontalAlignment;
-  LayoutEngine::VerticalAlignment mVerticalAlignment;
+  void Initialize( LineRun& line )
+  {
+    line.glyphRun.glyphIndex = 0u;
+    line.glyphRun.numberOfGlyphs = 0u;
+    line.characterRun.characterIndex = 0u;
+    line.characterRun.numberOfCharacters = 0u;
+    line.width = 0.f;
+    line.ascender = 0.f;
+    line.descender = 0.f;
+    line.extraLength = 0.f;
+    line.alignmentOffset = 0.f;
+    line.direction = !RTL;
+    line.ellipsis = false;
+    line.lineSpacing = mDefaultLineSpacing;
+  }
+
+  Type mLayout;
   float mCursorWidth;
+  float mDefaultLineSpacing;
+  float mPreviousCharacterExtraWidth;
 
   IntrusivePtr<Metrics> mMetrics;
-
-  bool mEllipsisEnabled:1;
 };
 
-LayoutEngine::LayoutEngine()
+Engine::Engine()
 : mImpl( NULL )
 {
-  mImpl = new LayoutEngine::Impl();
+  mImpl = new Engine::Impl();
 }
 
-LayoutEngine::~LayoutEngine()
+Engine::~Engine()
 {
   delete mImpl;
 }
 
-void LayoutEngine::SetMetrics( MetricsPtr& metrics )
+void Engine::SetMetrics( MetricsPtr& metrics )
 {
   mImpl->mMetrics = metrics;
 }
 
-void LayoutEngine::SetLayout( Layout layout )
+void Engine::SetLayout( Type layout )
 {
   mImpl->mLayout = layout;
 }
 
-LayoutEngine::Layout LayoutEngine::GetLayout() const
+Engine::Type Engine::GetLayout() const
 {
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "GetLayout[%d]\n", mImpl->mLayout);
   return mImpl->mLayout;
 }
 
-void LayoutEngine::SetTextEllipsisEnabled( bool enabled )
-{
-  mImpl->mEllipsisEnabled = enabled;
-}
-
-bool LayoutEngine::GetTextEllipsisEnabled() const
-{
-  return mImpl->mEllipsisEnabled;
-}
-
-void LayoutEngine::SetHorizontalAlignment( HorizontalAlignment alignment )
-{
-  mImpl->mHorizontalAlignment = alignment;
-}
-
-LayoutEngine::HorizontalAlignment LayoutEngine::GetHorizontalAlignment() const
-{
-  return mImpl->mHorizontalAlignment;
-}
-
-void LayoutEngine::SetVerticalAlignment( VerticalAlignment alignment )
-{
-  mImpl->mVerticalAlignment = alignment;
-}
-
-LayoutEngine::VerticalAlignment LayoutEngine::GetVerticalAlignment() const
-{
-  return mImpl->mVerticalAlignment;
-}
-
-void LayoutEngine::SetCursorWidth( int width )
+void Engine::SetCursorWidth( int width )
 {
   mImpl->mCursorWidth = static_cast<float>( width );
 }
 
-int LayoutEngine::GetCursorWidth() const
+int Engine::GetCursorWidth() const
 {
   return static_cast<int>( mImpl->mCursorWidth );
 }
 
-bool LayoutEngine::LayoutText( const LayoutParameters& layoutParameters,
-                               Vector<Vector2>& glyphPositions,
-                               Vector<LineRun>& lines,
-                               Size& layoutSize )
+bool Engine::LayoutText( const Parameters& layoutParameters,
+                         Vector<Vector2>& glyphPositions,
+                         Vector<LineRun>& lines,
+                         Size& layoutSize,
+                         bool elideTextEnabled )
 {
   return mImpl->LayoutText( layoutParameters,
                             glyphPositions,
                             lines,
-                            layoutSize );
+                            layoutSize,
+                            elideTextEnabled );
 }
 
-void LayoutEngine::ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters,
-                                             CharacterIndex startIndex,
-                                             Length numberOfCharacters,
-                                             Vector<Vector2>& glyphPositions )
+void Engine::ReLayoutRightToLeftLines( const Parameters& layoutParameters,
+                                       CharacterIndex startIndex,
+                                       Length numberOfCharacters,
+                                       Vector<Vector2>& glyphPositions )
 {
   mImpl->ReLayoutRightToLeftLines( layoutParameters,
                                    startIndex,
@@ -1275,17 +1290,33 @@ void LayoutEngine::ReLayoutRightToLeftLines( const LayoutParameters& layoutParam
                                    glyphPositions );
 }
 
-void LayoutEngine::Align( const Size& size,
-                          CharacterIndex startIndex,
-                          Length numberOfCharacters,
-                          Vector<LineRun>& lines )
+void Engine::Align( const Size& size,
+                    CharacterIndex startIndex,
+                    Length numberOfCharacters,
+                    Text::HorizontalAlignment::Type horizontalAlignment,
+                    Vector<LineRun>& lines,
+                    float& alignmentOffset )
 {
   mImpl->Align( size,
                 startIndex,
                 numberOfCharacters,
-                lines );
+                horizontalAlignment,
+                lines,
+                alignmentOffset );
+}
+
+void Engine::SetDefaultLineSpacing( float lineSpacing )
+{
+  mImpl->mDefaultLineSpacing = lineSpacing;
+}
+
+float Engine::GetDefaultLineSpacing() const
+{
+  return mImpl->mDefaultLineSpacing;
 }
 
+} // namespace Layout
+
 } // namespace Text
 
 } // namespace Toolkit