Fix for text alignmnet and scrolling. 52/37252/3
authorVictor Cebollada <v.cebollada@samsung.com>
Mon, 23 Mar 2015 07:32:13 +0000 (07:32 +0000)
committerVíctor Cebollada <v.cebollada@samsung.com>
Mon, 23 Mar 2015 16:59:39 +0000 (09:59 -0700)
Change-Id: Id800c1a6e8e53cef956d4d7633b6921f03cb5e82
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-engine.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h

index 3bf4e67..5cd3308 100644 (file)
@@ -412,9 +412,14 @@ void TextField::OnRelayout( const Vector2& size, ActorSizeContainer& container )
   if( mController->Relayout( size ) ||
       !mRenderer )
   {
+    const Vector2& scrollPosition = mController->GetScrollPosition();
+    const Vector2& alignmentOffset = mController->GetAlignmentOffset();
+
+    Vector2 offset = scrollPosition + alignmentOffset;
+
     if( mDecorator )
     {
-      mDecorator->Relayout( size, mController->GetScrollPosition() );
+      mDecorator->Relayout( size, offset );
     }
 
     if( !mRenderer )
@@ -438,8 +443,7 @@ void TextField::OnRelayout( const Vector2& size, ActorSizeContainer& container )
 
     if( mRenderableActor )
     {
-      const Vector2& scrollPosition = mController->GetScrollPosition();
-      mRenderableActor.SetPosition( scrollPosition.x, scrollPosition.y );
+      mRenderableActor.SetPosition( offset.x, offset.y );
 
       // Make sure the actor is parented correctly with/without clipping
       if( mClipper )
index 118c2b3..efcecbf 100644 (file)
@@ -291,6 +291,9 @@ void TextLabel::OnRelayout( const Vector2& size, ActorSizeContainer& container )
 
       if( renderableActor )
       {
+        const Vector2& alignmentOffset = mController->GetAlignmentOffset();
+        renderableActor.SetPosition( alignmentOffset.x, alignmentOffset.y );
+
         Self().Add( renderableActor );
       }
 
index 4e090e0..ebbf65b 100644 (file)
@@ -45,9 +45,10 @@ struct LineLayout
   Length         numberOfCharacters; ///< The number of characters which fit in one line.
   Length         numberOfGlyphs;     ///< The number of glyph which fit in one line.
   float          length;             ///< The length of the glyphs which fit in one line.
+  float          widthAdvanceDiff;   ///< The difference between the width and the advance of the last glyph.
   float          wsLengthEndOfLine;  ///< The length of the white spaces at the end of the line.
-  float          height;             ///< The maximum height of all fonts in the line.
   float          ascender;           ///< The maximum ascender of all fonts in the line.
+  float          descender;          ///< The maximum descender of all fonts in the line.
 };
 
 struct LayoutEngine::Impl
@@ -70,8 +71,8 @@ struct LayoutEngine::Impl
     lineLayout.numberOfGlyphs = 0u;
     lineLayout.length = 0.f;
     lineLayout.wsLengthEndOfLine = 0.f;
-    lineLayout.height = 0.f;
     lineLayout.ascender = 0.f;
+    lineLayout.descender = 0.f;
 
     // Get the last glyph index.
     const GlyphIndex lastGlyphIndex = parameters.totalNumberOfGlyphs - 1u;
@@ -121,18 +122,18 @@ struct LayoutEngine::Impl
         Text::FontMetrics fontMetrics;
         mFontClient.GetFontMetrics( glyphInfo.fontId, fontMetrics );
 
-        // Sets the maximum height.
-        if( fontMetrics.height > lineLayout.height )
-        {
-          lineLayout.height = fontMetrics.height;
-        }
-
         // Sets the maximum ascender.
         if( fontMetrics.ascender > lineLayout.ascender )
         {
           lineLayout.ascender = fontMetrics.ascender;
         }
 
+        // Sets the maximum descender.
+        if( fontMetrics.descender > lineLayout.descender )
+        {
+          lineLayout.descender = fontMetrics.descender;
+        }
+
         lastFontId = glyphInfo.fontId;
       }
     }
@@ -148,21 +149,20 @@ struct LayoutEngine::Impl
     lineLayout.numberOfCharacters = 0u;
     lineLayout.numberOfGlyphs = 0u;
     lineLayout.length = 0.f;
+    lineLayout.widthAdvanceDiff = 0.f;
     lineLayout.wsLengthEndOfLine = 0.f;
-    lineLayout.height = 0.f;
     lineLayout.ascender = 0.f;
+    lineLayout.descender = 0.f;
 
     // Stores temporary line layout which has not been added to the final line layout.
     LineLayout tmpLineLayout;
     tmpLineLayout.numberOfCharacters = 0u;
     tmpLineLayout.numberOfGlyphs = 0u;
     tmpLineLayout.length = 0.f;
+    tmpLineLayout.widthAdvanceDiff = 0.f;
     tmpLineLayout.wsLengthEndOfLine = 0.f;
-    tmpLineLayout.height = 0.f;
     tmpLineLayout.ascender = 0.f;
-
-    // Get the last glyph index.
-    const GlyphIndex lastGlyphIndex = parameters.totalNumberOfGlyphs - 1u;
+    tmpLineLayout.descender = 0.f;
 
     FontId lastFontId = 0u;
     for( GlyphIndex glyphIndex = lineLayout.glyphIndex;
@@ -200,18 +200,20 @@ struct LayoutEngine::Impl
       {
         // Add the length to the length of white spaces at the end of the line.
         tmpLineLayout.wsLengthEndOfLine += glyphInfo.advance; // I use the advance as the width is always zero for the white spaces.
+        tmpLineLayout.widthAdvanceDiff = 0.f;
       }
       else
       {
         // Add as well any previous white space length.
-        tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine + ( glyphIndex == lastGlyphIndex ) ? glyphInfo.width : glyphInfo.advance;
+        tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine + glyphInfo.advance;
+        tmpLineLayout.widthAdvanceDiff = glyphInfo.width - glyphInfo.advance;
 
         // Clear the white space length at the end of the line.
         tmpLineLayout.wsLengthEndOfLine = 0.f;
       }
 
       // Check if the accumulated length fits in the width of the box.
-      if( lineLayout.length + tmpLineLayout.length + ( ( 0.f < tmpLineLayout.length ) ? lineLayout.wsLengthEndOfLine : 0.f ) > parameters.boundingBox.width )
+      if( lineLayout.length + tmpLineLayout.length + tmpLineLayout.widthAdvanceDiff + ( ( 0.f < tmpLineLayout.length ) ? lineLayout.wsLengthEndOfLine : 0.f ) > parameters.boundingBox.width )
       {
         // Current word does not fit in the box's width.
         return;
@@ -223,6 +225,7 @@ struct LayoutEngine::Impl
         lineLayout.numberOfCharacters += tmpLineLayout.numberOfCharacters;
         lineLayout.numberOfGlyphs += tmpLineLayout.numberOfGlyphs;
         lineLayout.length += tmpLineLayout.length;
+        lineLayout.widthAdvanceDiff = tmpLineLayout.widthAdvanceDiff;
 
         if( 0.f < tmpLineLayout.length )
         {
@@ -235,22 +238,23 @@ struct LayoutEngine::Impl
           lineLayout.wsLengthEndOfLine += tmpLineLayout.wsLengthEndOfLine;
         }
 
-        if( tmpLineLayout.height > lineLayout.height )
+        if( tmpLineLayout.ascender > lineLayout.ascender )
         {
-          lineLayout.height = tmpLineLayout.height;
+          lineLayout.ascender = tmpLineLayout.ascender;
         }
 
-        if( tmpLineLayout.ascender > lineLayout.ascender )
+        if( tmpLineLayout.descender > lineLayout.descender )
         {
-          lineLayout.ascender = tmpLineLayout.ascender;
+          lineLayout.descender = tmpLineLayout.descender;
         }
 
         tmpLineLayout.numberOfCharacters = 0u;
         tmpLineLayout.numberOfGlyphs = 0u;
         tmpLineLayout.length = 0u;
+        tmpLineLayout.widthAdvanceDiff = 0u;
         tmpLineLayout.wsLengthEndOfLine = 0u;
-        tmpLineLayout.height = 0.f;
         tmpLineLayout.ascender = 0.f;
+        tmpLineLayout.descender = 0.f;
         return;
       }
 
@@ -261,6 +265,8 @@ struct LayoutEngine::Impl
         lineLayout.numberOfCharacters += tmpLineLayout.numberOfCharacters;
         lineLayout.numberOfGlyphs += tmpLineLayout.numberOfGlyphs;
         lineLayout.length += tmpLineLayout.length;
+        lineLayout.widthAdvanceDiff = tmpLineLayout.widthAdvanceDiff;
+
         if( 0.f < tmpLineLayout.length )
         {
           lineLayout.length += lineLayout.wsLengthEndOfLine;
@@ -272,22 +278,23 @@ struct LayoutEngine::Impl
           lineLayout.wsLengthEndOfLine += tmpLineLayout.wsLengthEndOfLine;
         }
 
-        if( tmpLineLayout.height > lineLayout.height )
+        if( tmpLineLayout.ascender > lineLayout.ascender )
         {
-          lineLayout.height = tmpLineLayout.height;
+          lineLayout.ascender = tmpLineLayout.ascender;
         }
 
-        if( tmpLineLayout.ascender > lineLayout.ascender )
+        if( tmpLineLayout.descender > lineLayout.descender )
         {
-          lineLayout.ascender = tmpLineLayout.ascender;
+          lineLayout.descender = tmpLineLayout.descender;
         }
 
         tmpLineLayout.numberOfCharacters = 0u;
         tmpLineLayout.numberOfGlyphs = 0u;
         tmpLineLayout.length = 0u;
+        tmpLineLayout.widthAdvanceDiff = 0u;
         tmpLineLayout.wsLengthEndOfLine = 0u;
-        tmpLineLayout.height = 0.f;
         tmpLineLayout.ascender = 0.f;
+        tmpLineLayout.descender = 0.f;
       }
 
       if( lastFontId != glyphInfo.fontId )
@@ -295,18 +302,18 @@ struct LayoutEngine::Impl
         Text::FontMetrics fontMetrics;
         mFontClient.GetFontMetrics( glyphInfo.fontId, fontMetrics );
 
-        // Sets the maximum height.
-        if( fontMetrics.height > tmpLineLayout.height )
-        {
-          tmpLineLayout.height = fontMetrics.height;
-        }
-
         // Sets the maximum ascender.
         if( fontMetrics.ascender > tmpLineLayout.ascender )
         {
           tmpLineLayout.ascender = fontMetrics.ascender;
         }
 
+        // Sets the maximum descender.
+        if( -fontMetrics.descender > tmpLineLayout.descender )
+        {
+          tmpLineLayout.descender = -fontMetrics.descender;
+        }
+
         lastFontId = glyphInfo.fontId;
       }
     }
@@ -382,6 +389,7 @@ struct LayoutEngine::Impl
   }
 
   void Align( const LayoutParameters& layoutParameters,
+              const Size& layoutSize,
               const Vector<LineRun>& lines,
               Vector<Vector2>& glyphPositions )
   {
@@ -423,7 +431,7 @@ struct LayoutEngine::Impl
 
       // 2) Calculate the alignment offset accordingly with the align option,
       //    the box width, line length, and the paragraphs direction.
-      float alignOffset = CalculateAlignment( layoutParameters.boundingBox.width,
+      float alignOffset = CalculateAlignment( layoutSize.width,
                                               line.lineSize.width,
                                               line.extraLength,
                                               paragraphDirection );
@@ -460,17 +468,17 @@ struct LayoutEngine::Impl
     lineRun.characterRun.characterIndex = 0u;
     lineRun.characterRun.numberOfCharacters = *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex );
     lineRun.lineSize.width = layout.length;
-    lineRun.lineSize.height = layout.height;
+    lineRun.lineSize.height = layout.ascender + layout.descender;
     lineRun.extraLength = layout.wsLengthEndOfLine;
 
     lines.PushBack( lineRun );
 
     // Update the actual size.
     actualSize.width = layout.length;
-    actualSize.height = layout.height;
+    actualSize.height = lineRun.lineSize.height;
 
     float penX = 0.f;
-    float penY = layout.height;
+    float penY = layout.ascender;
 
     Vector2* glyphPositionsBuffer = glyphPositions.Begin();
     for( GlyphIndex glyphIndex = 0u; glyphIndex < layout.numberOfGlyphs; ++glyphIndex )
@@ -517,23 +525,23 @@ struct LayoutEngine::Impl
       lineRun.numberOfGlyphs = layout.numberOfGlyphs;
       lineRun.characterRun.characterIndex = *( layoutParameters.glyphsToCharactersBuffer + index );
       lineRun.characterRun.numberOfCharacters = ( *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex ) ) - lineRun.characterRun.characterIndex;
-      lineRun.lineSize.width = layout.length;
-      lineRun.lineSize.height = layout.height;
+      lineRun.lineSize.width = layout.length + ( ( layout.widthAdvanceDiff > 0.f ) ? layout.widthAdvanceDiff : 0.f );
+      lineRun.lineSize.height = layout.ascender + layout.descender;
       lineRun.extraLength = layout.wsLengthEndOfLine;
 
       lines.PushBack( lineRun );
 
       // Update the actual size.
-      if( layout.length > actualSize.width )
+      if( layout.length + layout.widthAdvanceDiff > actualSize.width )
       {
         actualSize.width = layout.length;
       }
 
-      actualSize.height += layout.height;
+      actualSize.height += lineRun.lineSize.height;
 
       // Traverse the glyphs and set the positions.
 
-      penY += layout.height;
+      penY += layout.ascender;
 
       Vector2* glyphPositionsBuffer = glyphPositions.Begin();
       for( GlyphIndex i = index; i < index + layout.numberOfGlyphs; ++i )
@@ -547,6 +555,8 @@ struct LayoutEngine::Impl
         penX += glyph.advance;
       }
 
+      penY += layout.descender;
+
       // Increase the glyph index.
       index += layout.numberOfGlyphs;
     }
@@ -660,10 +670,12 @@ void LayoutEngine::ReLayoutRightToLeftLines( const LayoutParameters& layoutParam
 }
 
 void LayoutEngine::Align( const LayoutParameters& layoutParameters,
+                          const Size& layoutSize,
                           const Vector<LineRun>& lines,
                           Vector<Vector2>& glyphPositions )
 {
   mImpl->Align( layoutParameters,
+                layoutSize,
                 lines,
                 glyphPositions );
 }
index 093399b..1315445 100644 (file)
@@ -126,10 +126,12 @@ public:
    * @brief Aligns the laid out lines.
    *
    * @param[in] layoutParameters The parameters needed to layout the text.
+   * @param[in] layoutSize The size of the laid out the text.
    * @param[in] lines The laid-out lines.
    * @param[in,out] glyphPositions The positions of all the glyphs.
    */
   void Align( const LayoutParameters& layoutParameters,
+              const Size& layoutSize,
               const Vector<LineRun>& lines,
               Vector<Vector2>& glyphPositions );
 
index f6bc916..3981ce1 100644 (file)
@@ -135,7 +135,8 @@ struct Controller::TextInput
   /**
    * @brief Helper to move the cursor, grab handle etc.
    */
-  bool ProcessInputEvents( const Vector2& controlSize )
+  bool ProcessInputEvents( const Vector2& controlSize,
+                           const Vector2& alignmentOffset )
   {
     mDecoratorUpdated = false;
 
@@ -162,12 +163,12 @@ struct Controller::TextInput
           }
           case TAP_EVENT:
           {
-            OnTapEvent( *iter );
+            OnTapEvent( *iter, alignmentOffset );
             break;
           }
           case PAN_EVENT:
           {
-            OnPanEvent( *iter, controlSize );
+            OnPanEvent( *iter, controlSize, alignmentOffset );
             break;
           }
           case GRAB_HANDLE_EVENT:
@@ -230,7 +231,8 @@ struct Controller::TextInput
     // TODO
   }
 
-  void OnTapEvent( const Event& event )
+  void OnTapEvent( const Event& event,
+                   const Vector2& alignmentOffset  )
   {
     unsigned int tapCount = event.p1.mUint;
 
@@ -238,8 +240,8 @@ struct Controller::TextInput
     {
       ChangeState( EDITING );
 
-      float xPosition = event.p2.mFloat;
-      float yPosition = event.p3.mFloat;
+      float xPosition = event.p2.mFloat - alignmentOffset.x;
+      float yPosition = event.p3.mFloat - alignmentOffset.y;
       float height(0.0f);
       GetClosestCursorPosition( mPrimaryCursorPosition, xPosition, yPosition, height );
       mDecorator->SetPosition( PRIMARY_CURSOR, xPosition, yPosition, height );
@@ -254,7 +256,9 @@ struct Controller::TextInput
     }
   }
 
-  void OnPanEvent( const Event& event, const Vector2& controlSize )
+  void OnPanEvent( const Event& event,
+                   const Vector2& controlSize,
+                   const Vector2& alignmentOffset )
   {
     int state = event.p1.mInt;
 
@@ -265,28 +269,43 @@ struct Controller::TextInput
 
       if( mHorizontalScrollingEnabled )
       {
-        float displacementX = event.p2.mFloat;
+        const float displacementX = event.p2.mFloat;
         mScrollPosition.x += displacementX;
 
-        // Clamp between -space & 0
-        float contentWidth = actualSize.width;
-        float space = (contentWidth > controlSize.width) ? contentWidth - controlSize.width : 0.0f;
-        mScrollPosition.x = ( mScrollPosition.x < -space ) ? -space : mScrollPosition.x;
-        mScrollPosition.x = ( mScrollPosition.x > 0 )      ?      0 : mScrollPosition.x;
+        // Clamp between -space & 0 (and the text alignment).
+        const float contentWidth = actualSize.width;
+        if( contentWidth > controlSize.width )
+        {
+          const float space = ( contentWidth - controlSize.width ) + alignmentOffset.x;
+          mScrollPosition.x = ( mScrollPosition.x < -space ) ? -space : mScrollPosition.x;
+          mScrollPosition.x = ( mScrollPosition.x > -alignmentOffset.x ) ? -alignmentOffset.x : mScrollPosition.x;
 
-        mDecoratorUpdated = true;
+          mDecoratorUpdated = true;
+        }
+        else
+        {
+          mScrollPosition.x = 0.f;
+        }
       }
+
       if( mVerticalScrollingEnabled )
       {
-        float displacementY = event.p3.mFloat;
+        const float displacementY = event.p3.mFloat;
         mScrollPosition.y += displacementY;
 
-        // Clamp between -space & 0
-        float space = (actualSize.height > controlSize.height) ? actualSize.height - controlSize.height : 0.0f;
-        mScrollPosition.y = ( mScrollPosition.y < -space ) ? -space : mScrollPosition.y;
-        mScrollPosition.y = ( mScrollPosition.y > 0 )      ?      0 : mScrollPosition.y;
+        // Clamp between -space & 0 (and the text alignment).
+        if( actualSize.height > controlSize.height )
+        {
+          const float space = ( actualSize.height - controlSize.height ) + alignmentOffset.y;
+          mScrollPosition.y = ( mScrollPosition.y < -space ) ? -space : mScrollPosition.y;
+          mScrollPosition.y = ( mScrollPosition.y > -alignmentOffset.y ) ? -alignmentOffset.y : mScrollPosition.y;
 
-        mDecoratorUpdated = true;
+          mDecoratorUpdated = true;
+        }
+        else
+        {
+          mScrollPosition.y = 0.f;
+        }
       }
     }
   }
@@ -561,6 +580,7 @@ struct Controller::Impl
     mLayoutEngine(),
     mModifyEvents(),
     mControlSize(),
+    mAlignmentOffset(),
     mOperationsPending( NO_OPERATION ),
     mRecalculateNaturalSize( true )
   {
@@ -587,6 +607,7 @@ struct Controller::Impl
   LayoutEngine mLayoutEngine;              ///< The layout engine.
   std::vector<ModifyEvent> mModifyEvents;  ///< Temporary stores the text set until the next relayout.
   Size mControlSize;                       ///< The size of the control.
+  Vector2 mAlignmentOffset;                ///< Vertical and horizontal offset of the whole text inside the control due to alignment.
   OperationsMask mOperationsPending;       ///< Operations pending to be done to layout the text.
   bool mRecalculateNaturalSize:1;          ///< Whether the natural size needs to be recalculated.
 };
@@ -772,6 +793,11 @@ const Vector2& Controller::GetScrollPosition() const
   return Vector2::ZERO;
 }
 
+const Vector2& Controller::GetAlignmentOffset() const
+{
+  return mImpl->mAlignmentOffset;
+}
+
 Vector3 Controller::GetNaturalSize()
 {
   Vector3 naturalSize;
@@ -867,7 +893,7 @@ float Controller::GetHeightForWidth( float width )
   return layoutSize.height;
 }
 
-bool Controller::Relayout( const Vector2& size )
+bool Controller::Relayout( const Size& size )
 {
   if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
   {
@@ -906,10 +932,13 @@ bool Controller::Relayout( const Vector2& size )
   // Do not re-do any operation until something changes.
   mImpl->mOperationsPending = NO_OPERATION;
 
+  // After doing the text layout, the alignment offset to place the actor in the desired position can be calculated.
+  CalculateTextAlignment( size );
+
   if( mImpl->mTextInput )
   {
     // Move the cursor, grab handle etc.
-    updated = mImpl->mTextInput->ProcessInputEvents( mImpl->mControlSize ) || updated;
+    updated = mImpl->mTextInput->ProcessInputEvents( mImpl->mControlSize, mImpl->mAlignmentOffset ) || updated;
   }
 
   return updated;
@@ -1258,7 +1287,7 @@ void Controller::UpdateModel( OperationsMask operationsRequired )
   }
 }
 
-bool Controller::DoRelayout( const Vector2& size,
+bool Controller::DoRelayout( const Size& size,
                              OperationsMask operationsRequired,
                              Size& layoutSize )
 {
@@ -1368,6 +1397,7 @@ bool Controller::DoRelayout( const Vector2& size,
       if( ALIGN & operations )
       {
         mImpl->mLayoutEngine.Align( layoutParameters,
+                                    layoutSize,
                                     lines,
                                     glyphPositions );
       }
@@ -1387,6 +1417,53 @@ bool Controller::DoRelayout( const Vector2& size,
   return viewUpdated;
 }
 
+void Controller::CalculateTextAlignment( const Size& size )
+{
+  // TODO : Calculate the vertical offset.
+
+  // Get the direction of the first character.
+  const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u );
+
+  const Size& actualSize = mImpl->mVisualModel->GetActualSize();
+
+  // If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END;
+  LayoutEngine::Alignment alignment = mImpl->mLayoutEngine.GetAlignment();
+  if( firstParagraphDirection &&
+      ( LayoutEngine::ALIGN_CENTER != alignment ) )
+  {
+    if( LayoutEngine::ALIGN_BEGIN == alignment )
+    {
+      alignment = LayoutEngine::ALIGN_END;
+    }
+    else
+    {
+      alignment = LayoutEngine::ALIGN_BEGIN;
+    }
+  }
+
+  switch( alignment )
+  {
+    case LayoutEngine::ALIGN_BEGIN:
+    {
+      mImpl->mAlignmentOffset = Vector2::ZERO;
+      break;
+    }
+    case LayoutEngine::ALIGN_CENTER:
+    {
+      mImpl->mAlignmentOffset.y = 0.f;
+      const int intOffset = static_cast<int>( 0.5f * ( size.width - actualSize.width ) ); // try to avoid pixel alignment.
+      mImpl->mAlignmentOffset.x = static_cast<float>( intOffset );
+      break;
+    }
+    case LayoutEngine::ALIGN_END:
+    {
+      mImpl->mAlignmentOffset.y = 0.f;
+      mImpl->mAlignmentOffset.x = size.width - actualSize.width;
+      break;
+    }
+  }
+}
+
 View& Controller::GetView()
 {
   return mImpl->mView;
index cea9f39..2935299 100644 (file)
@@ -203,6 +203,13 @@ public:
   const Vector2& GetScrollPosition() const;
 
   /**
+   * @brief Query the alignment offset.
+   *
+   * @return The alignmnet offset.
+   */
+  const Vector2& GetAlignmentOffset() const;
+
+  /**
    * @copydoc Control::GetNaturalSize()
    */
   Vector3 GetNaturalSize();
@@ -219,7 +226,7 @@ public:
    * @param[in] size A the size of a bounding box to layout text within.
    * @return True if the text model or decorations were updated.
    */
-  bool Relayout( const Vector2& size );
+  bool Relayout( const Size& size );
 
   /**
    * @brief Process queued events which modify the model.
@@ -261,11 +268,18 @@ public:
    * @param[in] operations The layout operations which need to be done.
    * @param[out] layoutSize The size of the laid-out text.
    */
-  bool DoRelayout( const Vector2& size,
+  bool DoRelayout( const Size& size,
                    OperationsMask operations,
                    Size& layoutSize );
 
   /**
+   * @brief Calulates the alignment of the whole text inside the bounding box.
+   *
+   * @param[in] size The size of the bounding box.
+   */
+  void CalculateTextAlignment( const Size& size );
+
+  /**
    * @brief Return the layout engine.
    *
    * @return A reference to the layout engine.