Text Layout - Ellipsis the text when exceeds the boundaries of the box. 66/39266/9
authorVictor Cebollada <v.cebollada@samsung.com>
Fri, 8 May 2015 09:38:30 +0000 (10:38 +0100)
committerVictor Cebollada <v.cebollada@samsung.com>
Wed, 13 May 2015 12:52:28 +0000 (13:52 +0100)
Change-Id: I70d5be413e080bc75a0a9505736cc4170a1b69be
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
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/line-run.h
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp
dali-toolkit/internal/text/text-view-interface.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/text-view.h

index 3f0cf0d..a23eef3 100644 (file)
@@ -426,6 +426,10 @@ void TextLabel::OnInitialize()
   // Use height-for-width negotiation by default
   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
   self.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
+
+  // Enable the text ellipsis.
+  LayoutEngine& engine = mController->GetLayoutEngine();
+  engine.SetTextEllipsisEnabled( true );
 }
 
 void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
index 1589446..e037772 100644 (file)
@@ -98,7 +98,8 @@ struct LayoutEngine::Impl
   Impl()
   : mLayout( LayoutEngine::SINGLE_LINE_BOX ),
     mHorizontalAlignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN ),
-    mVerticalAlignment( LayoutEngine::VERTICAL_ALIGN_TOP )
+    mVerticalAlignment( LayoutEngine::VERTICAL_ALIGN_TOP ),
+    mEllipsisEnabled( false )
   {
     mFontClient = TextAbstraction::FontClient::Get();
   }
@@ -165,9 +166,14 @@ struct LayoutEngine::Impl
 
   /**
    * Retrieves the line layout for a given box width.
+   *
+   * @param[in] parameters The layout parameters.
+   * @param[out] lineLayout The line layout.
+   * @param[in] completelyFill Whether to completely fill the line ( even if the last word exceeds the boundaries ).
    */
   void GetLineLayoutForBox( const LayoutParameters& parameters,
-                            LineLayout& lineLayout )
+                            LineLayout& lineLayout,
+                            bool completelyFill )
   {
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->GetLineLayoutForBox\n" );
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  initial glyph index : %d\n", lineLayout.glyphIndex );
@@ -273,16 +279,16 @@ struct LayoutEngine::Impl
       }
 
       // Check if the accumulated length fits in the width of the box.
-      if( isMultiline && !isWhiteSpace &&
+      if( ( completelyFill || isMultiline ) && !isWhiteSpace &&
           ( lineLayout.length + lineLayout.wsLengthEndOfLine + tmpLineLayout.length + tmpLineLayout.widthAdvanceDiff > boundingBoxWidth ) )
       {
         // Current word does not fit in the box's width.
-        if( !oneWordLaidOut )
+        if( !oneWordLaidOut || completelyFill )
         {
           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  Break the word by character\n" );
 
           // The word's with doesn't fit in the control's with. It needs to be split by character.
-          if( tmpLineLayout.numberOfGlyphs > 1u )
+          if( tmpLineLayout.numberOfGlyphs > 0u )
           {
             tmpLineLayout.numberOfCharacters -= charactersPerGlyph;
             --tmpLineLayout.numberOfGlyphs;
@@ -336,13 +342,43 @@ struct LayoutEngine::Impl
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
   }
 
+  void SetGlyphPositions( const GlyphInfo* const glyphsBuffer,
+                          Length numberOfGlyphs,
+                          float penY,
+                          Vector2* glyphPositionsBuffer )
+  {
+    // Traverse the glyphs and set the positions.
+
+    // Check if the x bearing of the first character is negative.
+    // If it has a negative x bearing, it will exceed the boundaries of the actor,
+    // so the penX position needs to be moved to the right.
+    float penX = 0.f;
+
+    const GlyphInfo& glyph = *glyphsBuffer;
+    if( 0.f > glyph.xBearing )
+    {
+      penX = -glyph.xBearing;
+    }
+
+    for( GlyphIndex i = 0u; i < numberOfGlyphs; ++i )
+    {
+      const GlyphInfo& glyph = *( glyphsBuffer + i );
+      Vector2& position = *( glyphPositionsBuffer + i );
+
+      position.x = penX + glyph.xBearing;
+      position.y = penY - glyph.yBearing;
+
+      penX += glyph.advance;
+    }
+  }
+
   bool LayoutText( const LayoutParameters& layoutParameters,
                    Vector<Vector2>& glyphPositions,
                    Vector<LineRun>& lines,
                    Size& actualSize )
   {
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->LayoutText\n" );
-    Vector2* glyphPositionsBuffer = glyphPositions.Begin();
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  box size %f, %f\n", layoutParameters.boundingBox.width, layoutParameters.boundingBox.height );
 
     float penY = 0.f;
     for( GlyphIndex index = 0u; index < layoutParameters.totalNumberOfGlyphs; )
@@ -351,7 +387,8 @@ struct LayoutEngine::Impl
       LineLayout layout;
       layout.glyphIndex = index;
       GetLineLayoutForBox( layoutParameters,
-                           layout );
+                           layout,
+                           false );
 
       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "           glyph index %d\n", layout.glyphIndex );
       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "       character index %d\n", layout.characterIndex );
@@ -366,57 +403,108 @@ struct LayoutEngine::Impl
         return false;
       }
 
-      LineRun lineRun;
-      lineRun.glyphIndex = index;
-      lineRun.numberOfGlyphs = layout.numberOfGlyphs;
-      lineRun.characterRun.characterIndex = layout.characterIndex;
-      lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters;
-      lineRun.width = layout.length + layout.widthAdvanceDiff;
-      lineRun.ascender = layout.ascender;
-      lineRun.descender = layout.descender;
-      lineRun.extraLength = layout.wsLengthEndOfLine > 0.f ? layout.wsLengthEndOfLine - layout.widthAdvanceDiff : 0.f;
-      lineRun.direction = false;
-
-      lines.PushBack( lineRun );
-
-      // Update the actual size.
-      if( lineRun.width > actualSize.width )
+      // Set the line position. Discard if ellipsis is enabled and the position exceeds the boundaries
+      // of the box.
+      penY += layout.ascender;
+
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  pen y %f\n", penY );
+      if( mEllipsisEnabled &&
+          ( ( penY - layout.descender > layoutParameters.boundingBox.height ) ||
+            ( ( mLayout == SINGLE_LINE_BOX ) &&
+              ( layout.length + layout.widthAdvanceDiff > layoutParameters.boundingBox.width ) ) ) )
       {
-        actualSize.width = lineRun.width;
-      }
+        // Do not layout more lines if ellipsis is enabled.
 
-      actualSize.height += ( lineRun.ascender + -lineRun.descender );
+        // The last line needs to be completely filled with characters.
+        // Part of a word may be used.
 
-      // Traverse the glyphs and set the positions.
+        const Length numberOfLines = lines.Count();
 
-      penY += layout.ascender;
+        LineRun lineRun;
+        LineLayout ellipsisLayout;
+        if( 0u != numberOfLines )
+        {
+          // Get the last line and layout it again with the 'completelyFill' flag to true.
+          lineRun = *( lines.Begin() + ( numberOfLines - 1u ) );
 
-      // Check if the x bearing of the first character is negative.
-      // If it has a negative x bearing, it will exceed the boundaries of the actor,
-      // so the penX position needs to be moved to the right.
-      float penX = 0.f;
+          penY -= layout.ascender - lineRun.descender;
 
-      const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + index );
-      if( 0.f > glyph.xBearing )
-      {
-        penX = -glyph.xBearing;
-      }
+          ellipsisLayout.glyphIndex = lineRun.glyphIndex;
+        }
+        else
+        {
+          lineRun.glyphIndex = 0u;
+          ellipsisLayout.glyphIndex = 0u;
+        }
 
-      for( GlyphIndex i = index; i < index + layout.numberOfGlyphs; ++i )
-      {
-        const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + i );
-        Vector2& position = *( glyphPositionsBuffer + i );
+        GetLineLayoutForBox( layoutParameters,
+                             ellipsisLayout,
+                             true );
+
+        lineRun.numberOfGlyphs = ellipsisLayout.numberOfGlyphs;
+        lineRun.characterRun.characterIndex = ellipsisLayout.characterIndex;
+        lineRun.characterRun.numberOfCharacters = ellipsisLayout.numberOfCharacters;
+        lineRun.width = layoutParameters.boundingBox.width;
+        lineRun.ascender = ellipsisLayout.ascender;
+        lineRun.descender = ellipsisLayout.descender;
+        lineRun.extraLength = ellipsisLayout.wsLengthEndOfLine > 0.f ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.widthAdvanceDiff : 0.f;
+        lineRun.ellipsis = true;
+
+        actualSize.width = layoutParameters.boundingBox.width;
+        actualSize.height += ( lineRun.ascender + -lineRun.descender );
 
-        position.x = penX + glyph.xBearing;
-        position.y = penY - glyph.yBearing;
+        SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun.glyphIndex,
+                           ellipsisLayout.numberOfGlyphs,
+                           penY,
+                           glyphPositions.Begin() + lineRun.glyphIndex );
 
-        penX += glyph.advance;
+        if( 0u != numberOfLines )
+        {
+          // Set the last line with the ellipsis layout.
+          *( lines.Begin() + ( numberOfLines - 1u ) ) = lineRun;
+        }
+        else
+        {
+          // Push the line.
+          lines.PushBack( lineRun );
+        }
+
+        break;
       }
+      else
+      {
+        LineRun lineRun;
+        lineRun.glyphIndex = index;
+        lineRun.numberOfGlyphs = layout.numberOfGlyphs;
+        lineRun.characterRun.characterIndex = layout.characterIndex;
+        lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters;
+        lineRun.width = layout.length + layout.widthAdvanceDiff;
+        lineRun.ascender = layout.ascender;
+        lineRun.descender = layout.descender;
+        lineRun.extraLength = layout.wsLengthEndOfLine > 0.f ? layout.wsLengthEndOfLine - layout.widthAdvanceDiff : 0.f;
+        lineRun.direction = false;
+        lineRun.ellipsis = false;
+
+        lines.PushBack( lineRun );
+
+        // Update the actual size.
+        if( lineRun.width > actualSize.width )
+        {
+          actualSize.width = lineRun.width;
+        }
+
+        actualSize.height += ( lineRun.ascender + -lineRun.descender );
 
-      penY += -layout.descender;
+        SetGlyphPositions( layoutParameters.glyphsBuffer + index,
+                           layout.numberOfGlyphs,
+                           penY,
+                           glyphPositions.Begin() + index );
 
-      // Increase the glyph index.
-      index += layout.numberOfGlyphs;
+        penY += -layout.descender;
+
+        // Increase the glyph index.
+        index += layout.numberOfGlyphs;
+      }
     }
 
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText\n\n" );
@@ -584,6 +672,8 @@ struct LayoutEngine::Impl
   LayoutEngine::VerticalAlignment mVerticalAlignment;
 
   TextAbstraction::FontClient mFontClient;
+
+  bool mEllipsisEnabled:1;
 };
 
 LayoutEngine::LayoutEngine()
@@ -607,6 +697,16 @@ unsigned int LayoutEngine::GetLayout() const
   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;
index 0c17d68..42ff1aa 100644 (file)
@@ -90,6 +90,18 @@ public:
   unsigned int GetLayout() const;
 
   /**
+   * @brief Enable or disable the text ellipsis.
+   *
+   * @param[in] enabled Whether to enable the text ellipsis.
+   */
+  void SetTextEllipsisEnabled( bool enabled );
+
+  /**
+   * @return Whether the text ellipsis is enabled.
+   */
+  bool GetTextEllipsisEnabled() const;
+
+  /**
    * @brief Choose the required text horizontal alignment.
    *
    * @param[in] alignment The required alignment.
index a71dc0f..5668669 100644 (file)
@@ -45,7 +45,8 @@ struct LineRun
   float              ascender;       ///< The line's ascender.
   float              descender;      ///< The line's descender.
   float              extraLength;    ///< The length of the white spaces at the end of the line.
-  CharacterDirection direction;      ///< Direction of the first character of the paragraph.
+  CharacterDirection direction : 1;  ///< Direction of the first character of the paragraph.
+  bool               ellipsis  : 1;  ///< Wheter ellipsis is added to the line.
 };
 
 } // namespace Text
index 9e8a3fa..1306562 100644 (file)
@@ -25,6 +25,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/atlas-manager/atlas-manager.h>
+#include <dali-toolkit/internal/text/line-run.h>
 #include <dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h>
 #include <dali-toolkit/internal/text/rendering/shaders/text-basic-shader.h>
 #include <dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.h>
@@ -134,9 +135,9 @@ struct AtlasRenderer::Impl : public ConnectionTracker
 
     CalculateBlocksSize( glyphs );
 
-    for ( uint32_t i = 0; i < glyphs.Size(); ++i )
+    for( uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i )
     {
-      GlyphInfo glyph = glyphs[ i ];
+      const GlyphInfo& glyph = glyphs[ i ];
 
       // No operation for white space
       if ( glyph.width && glyph.height )
@@ -177,7 +178,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker
           }
         }
 
-        Vector2 position = positions[ i ];
+        const Vector2& position = positions[ i ];
         MeshData newMeshData;
         mGlyphManager.Cached( glyph.fontId, glyph.index, slot );
 
@@ -692,21 +693,25 @@ Text::RendererPtr AtlasRenderer::New()
 
 RenderableActor AtlasRenderer::Render( Text::ViewInterface& view )
 {
-
   UnparentAndReset( mImpl->mActor );
 
-  Text::Length numberOfGlyphs = view.GetNumberOfGlyphs();
+  Length numberOfGlyphs = view.GetNumberOfGlyphs();
 
-  if( numberOfGlyphs > 0 )
+  if( numberOfGlyphs > 0u )
   {
     Vector<GlyphInfo> glyphs;
     glyphs.Resize( numberOfGlyphs );
 
-    view.GetGlyphs( &glyphs[0], 0, numberOfGlyphs );
-
     std::vector<Vector2> positions;
     positions.resize( numberOfGlyphs );
-    view.GetGlyphPositions( &positions[0], 0, numberOfGlyphs );
+
+    numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
+                                     &positions[0],
+                                     0u,
+                                     numberOfGlyphs );
+    glyphs.Resize( numberOfGlyphs );
+    positions.resize( numberOfGlyphs );
+
     mImpl->AddGlyphs( positions,
                       glyphs,
                       view.GetTextColor(),
@@ -716,6 +721,7 @@ RenderableActor AtlasRenderer::Render( Text::ViewInterface& view )
                       view.GetUnderlineColor(),
                       view.GetUnderlineHeight() );
   }
+
   return mImpl->mActor;
 }
 
index 68ba70c..305abf7 100644 (file)
@@ -27,6 +27,7 @@
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/line-run.h>
 #include <dali-toolkit/internal/text/rendering/shaders/text-basic-shader.h>
 #include <dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.h>
 
@@ -347,18 +348,23 @@ RenderableActor BasicRenderer::Render( Text::ViewInterface& view )
   // Remove the previous text
   UnparentAndReset( mImpl->mActor );
 
-  Text::Length numberOfGlyphs = view.GetNumberOfGlyphs();
+  Length numberOfGlyphs = view.GetNumberOfGlyphs();
 
-  if( numberOfGlyphs > 0 )
+  if( numberOfGlyphs > 0u )
   {
     Vector<GlyphInfo> glyphs;
     glyphs.Resize( numberOfGlyphs );
 
-    view.GetGlyphs( &glyphs[0], 0, numberOfGlyphs );
-
     std::vector<Vector2> positions;
     positions.resize( numberOfGlyphs );
-    view.GetGlyphPositions( &positions[0], 0, numberOfGlyphs );
+
+    numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
+                                     &positions[0],
+                                     0u,
+                                     numberOfGlyphs );
+
+    glyphs.Resize( numberOfGlyphs );
+    positions.resize( numberOfGlyphs );
 
     mImpl->CreateAtlases( glyphs );
 
index 68d5e97..d8e2ae6 100644 (file)
@@ -35,6 +35,8 @@ namespace Toolkit
 namespace Text
 {
 
+struct LineRun;
+
 /**
  * @brief Abstract interface to provide the information necessary displaying text.
  *
@@ -65,28 +67,22 @@ public:
   virtual Length GetNumberOfGlyphs() const = 0;
 
   /**
-   * @brief Retrieves glyphs in the given buffer.
+   * @brief Retrieves glyphs and positions in the given buffers.
+   *
+   * @note The size of the @p glyphs and @p glyphPositions buffers need to be big enough to copy the @p numberOfGlyphs glyphs and positions.
+   * @note The returned number of glyphs may be less than @p numberOfGlyphs if a line has ellipsis.
    *
-   * The size of the @p glyphs buffer needs to be big enough to copy the @p numberOfGlyphs.
    * @param[out] glyphs Pointer to a buffer where the glyphs are copied.
+   * @param[out] glyphPositions Pointer to a buffer where the glyph positions are copied.
    * @param[in] glyphIndex Index to the first glyph.
    * @param[in] numberOfGlyphs Number of glyphs to be copied.
-   */
-  virtual void GetGlyphs( GlyphInfo* glyphs,
-                          GlyphIndex glyphIndex,
-                          Length numberOfGlyphs ) const = 0;
-
-  /**
-   * @brief Retrieves the glyph positions.
    *
-   * @pre The size of the @p positions buffer needs to be big enough to copy the @p numberOfGlyphs positions.
-   * @param[out] glyphPositions Pointer to a buffer where the glyph positions are copied.
-   * @param[in] glyphIndex Index to the first glyph position.
-   * @param[in] numberOfGlyphs The number of positions to be copied.
+   * @return The number of glyphs.
    */
-  virtual void GetGlyphPositions( Vector2* glyphPositions,
-                                  GlyphIndex glyphIndex,
-                                  Length numberOfGlyphs ) const = 0;
+  virtual Length GetGlyphs( GlyphInfo* glyphs,
+                            Vector2* glyphPositions,
+                            GlyphIndex glyphIndex,
+                            Length numberOfGlyphs ) const = 0;
 
   /**
    * @brief Retrieves the text color
index 61073fe..e7bd262 100644 (file)
@@ -20,6 +20,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/math/vector2.h>
+#include <dali/public-api/text-abstraction/font-client.h>
 
 namespace Dali
 {
@@ -33,12 +34,15 @@ namespace Text
 struct View::Impl
 {
   VisualModelPtr mVisualModel;
+  TextAbstraction::FontClient mFontClient; ///< Handle to the font client.
 };
 
 View::View()
 : mImpl( NULL )
 {
   mImpl = new View::Impl();
+
+  mImpl->mFontClient = TextAbstraction::FontClient::Get();
 }
 
 View::~View()
@@ -51,6 +55,139 @@ void View::SetVisualModel( VisualModelPtr visualModel )
   mImpl->mVisualModel = visualModel;
 }
 
+Length View::GetGlyphs( GlyphInfo* glyphs,
+                        Vector2* glyphPositions,
+                        GlyphIndex glyphIndex,
+                        Length numberOfGlyphs ) const
+{
+  Length numberOfLaidOutGlyphs = 0u;
+
+  if( mImpl->mVisualModel )
+  {
+    // If ellipsis is enabled, the number of glyphs the layout engine has laid out may be less than 'numberOfGlyphs'.
+    // Check the last laid out line to know if the layout engine elided some text.
+
+    const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines();
+    if( numberOfLines > 0u )
+    {
+      const LineRun& lastLine = *( mImpl->mVisualModel->mLines.Begin() + ( numberOfLines - 1u ) );
+
+      // If ellipsis is enabled, calculate the number of laid out glyphs.
+      // Otherwise use the given number of glyphs.
+      if( lastLine.ellipsis )
+      {
+        numberOfLaidOutGlyphs = lastLine.glyphIndex + lastLine.numberOfGlyphs;
+      }
+      else
+      {
+        numberOfLaidOutGlyphs = numberOfGlyphs;
+      }
+
+      // Retrieve from the visual model the glyphs and positions.
+      mImpl->mVisualModel->GetGlyphs( glyphs,
+                                      glyphIndex,
+                                      numberOfLaidOutGlyphs );
+
+      mImpl->mVisualModel->GetGlyphPositions( glyphPositions,
+                                              glyphIndex,
+                                              numberOfLaidOutGlyphs );
+
+      if( 1u == numberOfLaidOutGlyphs )
+      {
+        // not a point try to do ellipsis with only one laid out character.
+        return numberOfLaidOutGlyphs;
+      }
+
+      if( lastLine.ellipsis )
+      {
+        // firstPenX, penY and firstPenSet are used to position the ellipsis glyph if needed.
+        float firstPenX = 0.f; // Used if rtl text is elided.
+        float penY = 0.f;
+        bool firstPenSet = false;
+
+        // Add the ellipsis glyph.
+        bool inserted = false;
+        float removedGlypsWidth = 0.f;
+        Length numberOfRemovedGlyphs = 0u;
+        GlyphIndex index = numberOfLaidOutGlyphs - 1u;
+
+        // The ellipsis glyph has to fit in the place where the last glyph(s) is(are) removed.
+        while( !inserted )
+        {
+          const GlyphInfo& glyphToRemove = *( glyphs + index );
+
+          // Need to reshape the glyph as the font may be different in size.
+          const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph( mImpl->mFontClient.GetPointSize( glyphToRemove.fontId ) );
+
+          if( !firstPenSet )
+          {
+            const Vector2& position = *( glyphPositions + index );
+
+            // Calculates the penY of the current line. It will be used to position the ellipsis glyph.
+            penY = position.y + glyphToRemove.yBearing;
+
+            // Calculates the first penX which will be used if rtl text is elided.
+            firstPenX = position.x - glyphToRemove.xBearing;
+            if( firstPenX < -ellipsisGlyph.xBearing )
+            {
+              // Avoids to exceed the bounding box when rtl text is elided.
+              firstPenX = -ellipsisGlyph.xBearing;
+            }
+
+            removedGlypsWidth = -ellipsisGlyph.xBearing;
+
+            firstPenSet = true;
+          }
+
+          removedGlypsWidth += std::min( glyphToRemove.advance, ( glyphToRemove.xBearing + glyphToRemove.width ) );
+
+          // Calculate the width of the ellipsis glyph and check if it fits.
+          const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing;
+          if( ellipsisGlyphWidth < removedGlypsWidth )
+          {
+            GlyphInfo& glyphInfo = *( glyphs + index );
+            Vector2& position = *( glyphPositions + index );
+            position.x -= glyphInfo.xBearing;
+
+            // Replace the glyph by the ellipsis glyph.
+            glyphInfo = ellipsisGlyph;
+
+            // Change the 'x' and 'y' position of the ellipsis glyph.
+
+            if( position.x > firstPenX )
+            {
+              position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+            }
+
+            position.x += ellipsisGlyph.xBearing;
+            position.y = penY - ellipsisGlyph.yBearing;
+
+            inserted = true;
+          }
+          else
+          {
+            if( index > 0u )
+            {
+              --index;
+            }
+            else
+            {
+              // No space for the ellipsis.
+              inserted = true;
+            }
+            ++numberOfRemovedGlyphs;
+          }
+        }
+
+        // 'Removes' all the glyphs after the ellipsis glyph.
+        numberOfLaidOutGlyphs -= numberOfRemovedGlyphs;
+      }
+    }
+  }
+
+  return numberOfLaidOutGlyphs;
+}
+
 const Vector4& View::GetTextColor() const
 {
   if ( mImpl->mVisualModel )
@@ -128,26 +265,6 @@ Length View::GetNumberOfGlyphs() const
   return 0;
 }
 
-void View::GetGlyphs( GlyphInfo* glyphs,
-                      GlyphIndex glyphIndex,
-                      Length numberOfGlyphs ) const
-{
-  if( mImpl->mVisualModel )
-  {
-    mImpl->mVisualModel->GetGlyphs( glyphs, glyphIndex, numberOfGlyphs );
-  }
-}
-
-void View::GetGlyphPositions( Vector2* glyphPositions,
-                              GlyphIndex glyphIndex,
-                              Length numberOfGlyphs ) const
-{
-  if( mImpl->mVisualModel )
-  {
-    mImpl->mVisualModel->GetGlyphPositions( glyphPositions, glyphIndex, numberOfGlyphs );
-  }
-}
-
 } // namespace Text
 
 } // namespace Toolkit
index e611c3c..43506a5 100644 (file)
@@ -65,16 +65,10 @@ public:
   /**
    * @copydoc Dali::Toolkit::Text::ViewInterface::GetGlyphs()
    */
-  virtual void GetGlyphs( GlyphInfo* glyphs,
-                          GlyphIndex glyphIndex,
-                          Length numberOfGlyphs ) const;
-
-  /**
-   * @copydoc Dali::Toolkit::Text::ViewInterface::GetGlyphPositions()
-   */
-  virtual void GetGlyphPositions( Vector2* glyphPositions,
-                                  GlyphIndex glyphIndex,
-                                  Length numberOfGlyphs ) const;
+  virtual Length GetGlyphs( GlyphInfo* glyphs,
+                            Vector2* glyphPositions,
+                            GlyphIndex glyphIndex,
+                            Length numberOfGlyphs ) const;
 
   /**
    * @copydoc Dali::Toolkit::Text::ViewInterface::GetTextColor()