Layout implementation 30/36430/2
authorVictor Cebollada <v.cebollada@samsung.com>
Fri, 6 Mar 2015 08:35:52 +0000 (08:35 +0000)
committerVictor Cebollada <v.cebollada@samsung.com>
Fri, 6 Mar 2015 11:53:40 +0000 (11:53 +0000)
Change-Id: Id9f6ca5cbd948a718c35d0856a9577ec86862568
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-engine.h
dali-toolkit/internal/text/layouts/layout-parameters.h [new file with mode: 0644]
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h

index ac2c53f..b5c3b16 100644 (file)
@@ -23,8 +23,7 @@
 #include <dali/public-api/text-abstraction/font-client.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/logical-model.h>
-#include <dali-toolkit/internal/text/visual-model.h>
+#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
 
 namespace Dali
 {
@@ -35,6 +34,21 @@ namespace Toolkit
 namespace Text
 {
 
+/**
+ * @brief Stores temporary layout info of the line.
+ */
+struct LineLayout
+{
+  GlyphIndex     glyphIndex;         ///< Index of the first glyph to be laid-out.
+  CharacterIndex characterIndex;     ///< Index of the first character to be laid-out.
+  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          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.
+};
+
 struct LayoutEngine::Impl
 {
   Impl()
@@ -43,169 +57,346 @@ struct LayoutEngine::Impl
     mFontClient = TextAbstraction::FontClient::Get();
   }
 
-  void UpdateVisualModel( const Vector2& boundingBox,
-                          const Vector<GlyphInfo>& glyphs,
-                          const Vector<CharacterIndex>& characterIndices,
-                          const Vector<Length>& charactersPerGlyph,
-                          VisualModel& visualModel )
+  /**
+   * Retrieves the line layout for a given box width.
+   */
+  void GetLineLayoutForBox( const LayoutParameters& parameters,
+                            LineLayout& lineLayout )
   {
-    // TODO Switch between different layouts
+    // Initializes the line layout.
+    lineLayout.numberOfCharacters = 0u;
+    lineLayout.numberOfGlyphs = 0u;
+    lineLayout.length = 0.f;
+    lineLayout.wsLengthEndOfLine = 0.f;
+    lineLayout.height = 0.f;
+    lineLayout.ascender = 0.f;
+
+    // Get the last glyph index.
+    const GlyphIndex lastGlyphIndex = parameters.totalNumberOfGlyphs - 1u;
+
+    FontId lastFontId = 0u;
+    for( GlyphIndex glyphIndex = lineLayout.glyphIndex;
+         glyphIndex < parameters.totalNumberOfGlyphs;
+         ++glyphIndex )
+    {
+      // Get the glyph info.
+      const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + glyphIndex );
 
-    visualModel.SetGlyphs( &glyphs[0],
-                           &characterIndices[0],
-                           &charactersPerGlyph[0],
-                           glyphs.Count() );
+      // Get the character indices for the current glyph. The last character index is needed
+      // because there are glyphs formed by more than one character but their break info is
+      // given only for the last character.
+      const Length charactersPerGlyph = *( parameters.charactersPerGlyphBuffer + glyphIndex );
+      const CharacterIndex characterFirstIndex = *( parameters.glyphsToCharactersBuffer + glyphIndex );
+      const CharacterIndex characterLastIndex = characterFirstIndex + ( ( 1u > charactersPerGlyph ) ? 0u : charactersPerGlyph - 1u );
 
-    UpdateGlyphPositions( boundingBox, visualModel );
-  }
+      // Get the line break info for the current character.
+      const LineBreakInfo lineBreakInfo = *( parameters.lineBreakInfoBuffer + characterLastIndex );
 
-  void UpdateGlyphPositions( const Vector2& boundingBox, VisualModel& visualModel )
-  {
-    if( LayoutEngine::SINGLE_LINE_BOX == mLayout )
-    {
-      SingleLineLayout( boundingBox, visualModel );
-    }
-    else
-    {
-      MultiLineLayout( boundingBox, visualModel );
-    }
-  }
+      // Get the word break info for the current character.
+      const WordBreakInfo wordBreakInfo = *( parameters.wordBreakInfoBuffer + characterLastIndex );
 
-  // TODO - Rewrite this to handle bidi
-  void SingleLineLayout( const Vector2& boundingBox, VisualModel& visualModel )
-  {
-    Length glyphCount = visualModel.GetNumberOfGlyphs();
-
-    std::vector<Vector2> glyphPositions;
-    glyphPositions.reserve( glyphCount );
+      // Increase the number of characters.
+      lineLayout.numberOfCharacters += charactersPerGlyph;
 
-    if( glyphCount > 0 )
-    {
-      // FIXME Single font assumption
-      Text::FontMetrics fontMetrics;
-      GlyphInfo firstGlyph;
-      visualModel.GetGlyphs( &firstGlyph, 0, 1 );
-      mFontClient.GetFontMetrics( firstGlyph.fontId, fontMetrics );
+      // Increase the number of glyphs.
+      lineLayout.numberOfGlyphs++;
 
-      float penX( 0 );
-      float penY( fontMetrics.ascender ); // Move to baseline
+      // Increase the accumulated length.
+      lineLayout.length += ( glyphIndex == lastGlyphIndex ) ? glyphInfo.width : glyphInfo.advance;
 
-      for( unsigned int i=0; i<glyphCount; ++i )
+      if( TextAbstraction::LINE_MUST_BREAK == lineBreakInfo )
+      {
+      }
+      if( TextAbstraction::WORD_BREAK == wordBreakInfo )
       {
-        GlyphInfo glyph;
-        visualModel.GetGlyphs( &glyph, i, 1 );
+      }
 
-        glyphPositions.push_back( Vector2( penX + glyph.xBearing,
-                                           penY - glyph.yBearing ) );
+      if( lastFontId != glyphInfo.fontId )
+      {
+        Text::FontMetrics fontMetrics;
+        mFontClient.GetFontMetrics( glyphInfo.fontId, fontMetrics );
 
-        penX += glyph.advance;
-      }
+        // Sets the maximum height.
+        if( fontMetrics.height > lineLayout.height )
+        {
+          lineLayout.height = fontMetrics.height;
+        }
 
-      visualModel.SetGlyphPositions( &glyphPositions[0], glyphCount );
+        // Sets the maximum ascender.
+        if( fontMetrics.ascender > lineLayout.ascender )
+        {
+          lineLayout.ascender = fontMetrics.ascender;
+        }
 
-      visualModel.SetActualSize( Vector2(penX, fontMetrics.height) );
+        lastFontId = glyphInfo.fontId;
+      }
     }
   }
 
-  // TODO - Rewrite this to handle bidi
-  void MultiLineLayout( const Vector2& boundingBox, VisualModel& visualModel )
+  /**
+   * Retrieves the line layout for a given box width.
+   */
+  void GetMultiLineLayoutForBox( const LayoutParameters& parameters,
+                                 LineLayout& lineLayout )
   {
-    Length glyphCount = visualModel.GetNumberOfGlyphs();
+    // Initializes the line layout.
+    lineLayout.numberOfCharacters = 0u;
+    lineLayout.numberOfGlyphs = 0u;
+    lineLayout.length = 0.f;
+    lineLayout.wsLengthEndOfLine = 0.f;
+    lineLayout.height = 0.f;
+    lineLayout.ascender = 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.wsLengthEndOfLine = 0.f;
+    tmpLineLayout.height = 0.f;
+    tmpLineLayout.ascender = 0.f;
+
+    // Get the last glyph index.
+    const GlyphIndex lastGlyphIndex = parameters.totalNumberOfGlyphs - 1u;
+
+    FontId lastFontId = 0u;
+    for( GlyphIndex glyphIndex = lineLayout.glyphIndex;
+         glyphIndex < parameters.totalNumberOfGlyphs;
+         ++glyphIndex )
+    {
+      // Get the glyph info.
+      const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + glyphIndex );
 
-    std::vector<Vector2> glyphPositions;
-    glyphPositions.reserve( glyphCount );
+      // Get the character indices for the current glyph. The last character index is needed
+      // because there are glyphs formed by more than one character but their break info is
+      // given only for the last character.
+      const Length charactersPerGlyph = *( parameters.charactersPerGlyphBuffer + glyphIndex );
+      const CharacterIndex characterFirstIndex = *( parameters.glyphsToCharactersBuffer + glyphIndex );
+      const CharacterIndex characterLastIndex = characterFirstIndex + ( ( 1u > charactersPerGlyph ) ? 0u : charactersPerGlyph - 1u );
 
-    if( glyphCount > 0 )
-    {
-      Size actualSize;
+      // Get the line break info for the current character.
+      const LineBreakInfo lineBreakInfo = *( parameters.lineBreakInfoBuffer + characterLastIndex );
 
-      // FIXME Single font assumption
-      Text::FontMetrics fontMetrics;
-      GlyphInfo firstGlyph;
-      visualModel.GetGlyphs( &firstGlyph, 0, 1 );
-      mFontClient.GetFontMetrics( firstGlyph.fontId, fontMetrics );
+      // Get the word break info for the current character.
+      const WordBreakInfo wordBreakInfo = *( parameters.wordBreakInfoBuffer + characterLastIndex );
 
-      float penX( 0 );
-      float penY( fontMetrics.ascender ); // Move to baseline
+      // Increase the number of characters.
+      tmpLineLayout.numberOfCharacters += charactersPerGlyph;
 
-      unsigned int i=0;
-      while( i < glyphCount )
+      // Increase the number of glyphs.
+      tmpLineLayout.numberOfGlyphs++;
+
+      // Increase the accumulated length.
+      tmpLineLayout.length += ( glyphIndex == lastGlyphIndex ) ? glyphInfo.width : glyphInfo.advance;
+
+      // Check if the accumulated length fits in the width of the box.
+      if( lineLayout.length + tmpLineLayout.length > parameters.boundingBox.width )
+      {
+        // Current word does not fit in the box's width.
+        return;
+      }
+
+      if( TextAbstraction::LINE_MUST_BREAK == lineBreakInfo )
       {
-        // Skip initial whitespace
-        for( ; i<glyphCount; ++i )
+        if( glyphIndex == lastGlyphIndex )
         {
-          GlyphInfo glyph;
-          visualModel.GetGlyphs( &glyph, i, 1 );
+          // Must break the line. Update the line layout and return.
+          lineLayout.numberOfCharacters += tmpLineLayout.numberOfCharacters;
+          lineLayout.numberOfGlyphs += tmpLineLayout.numberOfGlyphs;
+          lineLayout.length += tmpLineLayout.length;
+          lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
 
-          if( glyph.width  > 0 &&
-              glyph.height > 0 )
+          if( tmpLineLayout.height > lineLayout.height )
           {
-            break;
+            lineLayout.height = tmpLineLayout.height;
           }
-          else
+
+          if( tmpLineLayout.ascender > lineLayout.ascender )
           {
-            glyphPositions.push_back( Vector2( penX + glyph.xBearing,
-                                               penY - glyph.yBearing ) );
+            lineLayout.ascender = tmpLineLayout.ascender;
           }
         }
 
-        // Find last glyph for the next line
-        unsigned int endIndex = i;
-        float endPenX = penX;
-        unsigned int j=i;
-        for( ; j<glyphCount; ++j )
-        {
-          GlyphInfo glyph;
-          visualModel.GetGlyphs( &glyph, j, 1 );
+        tmpLineLayout.numberOfCharacters = 0u;
+        tmpLineLayout.numberOfGlyphs = 0u;
+        tmpLineLayout.length = 0u;
+        tmpLineLayout.wsLengthEndOfLine = 0u;
+        tmpLineLayout.height = 0.f;
+        tmpLineLayout.ascender = 0.f;
+        return;
+      }
 
-          endPenX += glyph.advance;
+      if( TextAbstraction::WORD_BREAK == wordBreakInfo )
+      {
+        // Current glyph is the last one of the current word.
+        // Add the temporal layout to the current one.
+        lineLayout.numberOfCharacters += tmpLineLayout.numberOfCharacters;
+        lineLayout.numberOfGlyphs += tmpLineLayout.numberOfGlyphs;
+        lineLayout.length += tmpLineLayout.length;
+        lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
+
+        if( tmpLineLayout.height > lineLayout.height )
+        {
+          lineLayout.height = tmpLineLayout.height;
+        }
 
-          if( glyph.width  <= 0 ||
-              glyph.height <= 0 )
-          {
-            // Potential line end found
-            endIndex = j;
-          }
-          else if( endPenX > boundingBox.width )
-          {
-            break;
-          }
+        if( tmpLineLayout.ascender > lineLayout.ascender )
+        {
+          lineLayout.ascender = tmpLineLayout.ascender;
         }
 
-        actualSize.width = ( actualSize.width < endPenX ) ? endPenX : actualSize.width;
+        tmpLineLayout.numberOfCharacters = 0u;
+        tmpLineLayout.numberOfGlyphs = 0u;
+        tmpLineLayout.length = 0u;
+        tmpLineLayout.wsLengthEndOfLine = 0u;
+        tmpLineLayout.height = 0.f;
+        tmpLineLayout.ascender = 0.f;
+      }
+
+      if( lastFontId != glyphInfo.fontId )
+      {
+        Text::FontMetrics fontMetrics;
+        mFontClient.GetFontMetrics( glyphInfo.fontId, fontMetrics );
 
-        // If end of text or no whitespace found
-        if( glyphCount == j ||
-            endIndex == i )
+        // Sets the maximum height.
+        if( fontMetrics.height > tmpLineLayout.height )
         {
-          endIndex = j;
+          tmpLineLayout.height = fontMetrics.height;
         }
 
-        for( ; i<endIndex; ++i )
+        // Sets the maximum ascender.
+        if( fontMetrics.ascender > tmpLineLayout.ascender )
         {
-          GlyphInfo glyph;
-          visualModel.GetGlyphs( &glyph, i, 1 );
+          tmpLineLayout.ascender = fontMetrics.ascender;
+        }
 
-          glyphPositions.push_back( Vector2( penX + glyph.xBearing,
-                                             penY - glyph.yBearing ) );
+        lastFontId = glyphInfo.fontId;
+      }
+    }
+  }
 
-          penX += glyph.advance;
-        }
+  bool LayoutText( const LayoutParameters& layoutParameters,
+                   Vector<Vector2>& glyphPositions,
+                   Size& actualSize )
+  {
+    // TODO Switch between different layouts
+    bool update = false;
 
-        // Go to next line
-        penX = 0;
-        penY += fontMetrics.height;
+    switch( mLayout )
+    {
+      case LayoutEngine::SINGLE_LINE_BOX:
+      {
+        update = SingleLineLayout( layoutParameters,
+                                   glyphPositions,
+                                   actualSize );
+        break;
+      }
+      case LayoutEngine::MULTI_LINE_BOX:
+      {
+        update = MultiLineLayout( layoutParameters,
+                                  glyphPositions,
+                                  actualSize );
+        break;
+      }
+      default:
+        break;
+    }
+
+    return update;
+  }
+
+  // TODO - Rewrite this to handle bidi
+  bool SingleLineLayout( const LayoutParameters& layoutParameters,
+                         Vector<Vector2>& glyphPositions,
+                         Size& actualSize )
+  {
+    LineLayout layout;
+    layout.glyphIndex = 0u;
+    GetLineLayoutForBox( layoutParameters,
+                         layout );
 
-        actualSize.height += fontMetrics.height;
+    if( 0u == layout.numberOfGlyphs )
+    {
+      // The width is too small and no characters are laid-out.
+      return false;
+    }
+
+    // Update the actual size.
+    actualSize.width = layout.length;
+    actualSize.height = layout.height;
+
+    float penX = 0.f;
+    float penY = layout.height;
+
+    Vector2* glyphPositionsBuffer = glyphPositions.Begin();
+    for( GlyphIndex glyphIndex = 0u; glyphIndex < layout.numberOfGlyphs; ++glyphIndex )
+    {
+      const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + glyphIndex );
+      Vector2& position = *( glyphPositionsBuffer + glyphIndex );
+
+      position.x = penX + glyph.xBearing;
+      position.y = penY - glyph.yBearing;
+
+      penX += glyph.advance;
+    }
+
+    return true;
+  }
+
+  // TODO - Rewrite this to handle bidi
+  bool MultiLineLayout( const LayoutParameters& layoutParameters,
+                        Vector<Vector2>& glyphPositions,
+                        Size& actualSize )
+  {
+    float penY = 0.f;
+    for( GlyphIndex index = 0u; index < layoutParameters.totalNumberOfGlyphs; )
+    {
+      float penX = 0.f;
+
+      // Get the layout for the line.
+      LineLayout layout;
+      layout.glyphIndex = index;
+      GetMultiLineLayoutForBox( layoutParameters,
+                                layout );
+
+      if( 0u == layout.numberOfGlyphs )
+      {
+        // The width is too small and no characters are laid-out.
+        return false;
       }
 
-      visualModel.SetGlyphPositions( &glyphPositions[0], glyphCount );
+      // Update the actual size.
+      if( layout.length > actualSize.width )
+      {
+        actualSize.width = layout.length;
+      }
+
+      actualSize.height += layout.height;
+
+      // Traverse the glyphs and set the positions.
+
+      penY += layout.height;
+
+      Vector2* glyphPositionsBuffer = glyphPositions.Begin();
+      for( GlyphIndex i = index; i < index + layout.numberOfGlyphs; ++i )
+      {
+        const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + i );
+        Vector2& position = *( glyphPositionsBuffer + i );
+
+        position.x = penX + glyph.xBearing;
+        position.y = penY - glyph.yBearing;
+
+        penX += glyph.advance;
+      }
 
-      visualModel.SetActualSize( actualSize );
+      // Increase the glyph index.
+      index += layout.numberOfGlyphs;
     }
+
+    return true;
   }
 
-  unsigned int mLayout;
+  LayoutEngine::Layout mLayout;
 
   TextAbstraction::FontClient mFontClient;
 };
@@ -231,17 +422,13 @@ unsigned int LayoutEngine::GetLayout() const
   return mImpl->mLayout;
 }
 
-void LayoutEngine::UpdateVisualModel( const Vector2& boundingBox,
-                                      const Vector<GlyphInfo>& glyphs,
-                                      const Vector<CharacterIndex>& characterIndices,
-                                      const Vector<Length>& charactersPerGlyph,
-                                      VisualModel& visualModel )
+bool LayoutEngine::LayoutText( const LayoutParameters& layoutParameters,
+                               Vector<Vector2>& glyphPositions,
+                               Size& actualSize )
 {
-  mImpl->UpdateVisualModel( boundingBox,
-                            glyphs,
-                            characterIndices,
-                            charactersPerGlyph,
-                            visualModel );
+  return mImpl->LayoutText( layoutParameters,
+                            glyphPositions,
+                            actualSize );
 }
 
 } // namespace Text
index d3ae55a..febf485 100644 (file)
@@ -23,6 +23,7 @@
 
 // EXTERNAL INCLUDE
 #include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/math/vector2.h>
 
 namespace Dali
 {
@@ -35,7 +36,7 @@ namespace Toolkit
 namespace Text
 {
 
-class VisualModel;
+struct LayoutParameters;
 
 /**
  * @brief LayoutEngine is responsible for calculating the visual position of glyphs in layout.
@@ -77,17 +78,15 @@ public:
   /**
    * @brief Store the visual position of glyphs in the VisualModel.
    *
-   * @param[in] boundingBox The size of the box containing the text.
-   * @param[in] glyphs A vector with glyphs.
-   * @param[in] characterIndices Vector with indices pointing the first character of each glyph.
-   * @param[in] charactersPerGlyph Vector with the number of characters that forms each glyph.
-   * @param[in] visualModel The visual model to update.
+   * @param[in] layoutParameters The parameters needed to layout the text.
+   * @param[out] glyphPositions The positions of all the glyphs.
+   * @param[out] actualSize The size of the text after it has been laid-out.
+   *
+   * @return \e true if the text has been re-laid-out. \e false means the given width is too small to layout even a single character.
    */
-  void UpdateVisualModel( const Vector2& boundingBox,
-                          const Vector<GlyphInfo>& glyphs,
-                          const Vector<CharacterIndex>& characterIndices,
-                          const Vector<Length>& charactersPerGlyph,
-                          VisualModel& visualModel );
+  bool LayoutText( const LayoutParameters& layoutParameters,
+                   Vector<Vector2>& glyphPositions,
+                   Size& actualSize );
 
 private:
 
diff --git a/dali-toolkit/internal/text/layouts/layout-parameters.h b/dali-toolkit/internal/text/layouts/layout-parameters.h
new file mode 100644 (file)
index 0000000..9fa4dde
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __DALI_TOOLKIT_TEXT_LAYOUT_PARAMETERS_H__
+#define __DALI_TOOLKIT_TEXT_LAYOUT_PARAMETERS_H__
+
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/math/vector2.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief Struct used to pass parameters.
+ */
+struct LayoutParameters
+{
+  /**
+   * Constructor with the needed parameters to layout the text.
+   *
+   * @param[in] boundingBox The size of the box containing the text.
+   * @param[in] lineBreakInfoBuffer The line break info.
+   * @param[in] wordBreakInfoBuffer The word break info.
+   * @param[in] totalNumberOfGlyphs The number of glyphs.
+   * @param[in] glyphsBuffer A vector with glyphs.
+   * @param[in] glyphsToCharactersBuffer Vector with indices pointing the first character of each glyph.
+   * @param[in] charactersPerGlyphBuffer Vector with the number of characters that forms each glyph.
+   */
+  LayoutParameters( const Vector2& boundingBox,
+                    const LineBreakInfo* const lineBreakInfoBuffer,
+                    const WordBreakInfo* const wordBreakInfoBuffer,
+                    Length totalNumberOfGlyphs,
+                    const GlyphInfo* const glyphsBuffer,
+                    const CharacterIndex* const glyphsToCharactersBuffer,
+                    const Length* const charactersPerGlyphBuffer )
+  : boundingBox( boundingBox ),
+    lineBreakInfoBuffer( lineBreakInfoBuffer ),
+    wordBreakInfoBuffer( wordBreakInfoBuffer ),
+    totalNumberOfGlyphs( totalNumberOfGlyphs ),
+    glyphsBuffer( glyphsBuffer ),
+    glyphsToCharactersBuffer( glyphsToCharactersBuffer ),
+    charactersPerGlyphBuffer( charactersPerGlyphBuffer )
+  {}
+
+  Vector2                     boundingBox;
+  const LineBreakInfo* const  lineBreakInfoBuffer;
+  const WordBreakInfo* const  wordBreakInfoBuffer;
+  Length                      totalNumberOfGlyphs;
+  const GlyphInfo* const      glyphsBuffer;
+  const CharacterIndex* const glyphsToCharactersBuffer;
+  const Length* const         charactersPerGlyphBuffer;
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_LAYOUT_PARAMETERS_H__
index 67f91c4..995354c 100644 (file)
@@ -21,6 +21,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
+#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
 #include <dali-toolkit/internal/text/logical-model.h>
 #include <dali-toolkit/internal/text/multi-language-support.h>
 #include <dali-toolkit/internal/text/script-run.h>
@@ -381,7 +382,7 @@ bool Controller::DoRelayout( const Vector2& size, OperationsMask operations )
     mImpl->mLogicalModel->SetText( utf32Characters.Begin(), characterCount );
 
     // Discard temporary text
-    text.clear();
+    //text.clear(); temporary keep the text. will be fixed in the next patch.
   }
 
   Vector<LineBreakInfo> lineBreakInfo;
@@ -399,6 +400,18 @@ bool Controller::DoRelayout( const Vector2& size, OperationsMask operations )
     mImpl->mLogicalModel->SetLineBreakInfo( lineBreakInfo.Begin(), characterCount );
   }
 
+  Vector<WordBreakInfo> wordBreakInfo;
+  if( GET_WORD_BREAKS & operations )
+  {
+    // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
+    wordBreakInfo.Resize( characterCount, TextAbstraction::WORD_NO_BREAK );
+
+    SetWordBreakInfo( utf32Characters,
+                      wordBreakInfo );
+
+    mImpl->mLogicalModel->SetWordBreakInfo( wordBreakInfo.Begin(), characterCount );
+  }
+
   const bool getScripts = GET_SCRIPTS & operations;
   const bool validateFonts = VALIDATE_FONTS & operations;
 
@@ -454,16 +467,37 @@ bool Controller::DoRelayout( const Vector2& size, OperationsMask operations )
     mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), glyphs.Count() );
   }
 
+  Length numberOfGlyphs = glyphs.Count();
+  if( 0u != numberOfGlyphs )
+  {
+    // Sets the glyphs into the model.
+    mImpl->mVisualModel->SetGlyphs( glyphs.Begin(),
+                                    glyphsToCharactersMap.Begin(),
+                                    charactersPerGlyph.Begin(),
+                                    numberOfGlyphs );
+  }
+
   if( LAYOUT & operations )
   {
-    if( 0u == glyphs.Count() )
+    if( 0u == numberOfGlyphs )
     {
-      const Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
+      const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
+      numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
 
+      lineBreakInfo.Resize( numberOfCharacters );
+      wordBreakInfo.Resize( numberOfCharacters );
       glyphs.Resize( numberOfGlyphs );
       glyphsToCharactersMap.Resize( numberOfGlyphs );
       charactersPerGlyph.Resize( numberOfGlyphs );
 
+      mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(),
+                                              0u,
+                                              numberOfCharacters );
+
+      mImpl->mLogicalModel->GetWordBreakInfo( wordBreakInfo.Begin(),
+                                              0u,
+                                              numberOfCharacters );
+
       mImpl->mVisualModel->GetGlyphs( glyphs.Begin(),
                                       0u,
                                       numberOfGlyphs );
@@ -477,14 +511,32 @@ bool Controller::DoRelayout( const Vector2& size, OperationsMask operations )
                                                      numberOfGlyphs );
     }
 
+    // Set the layout parameters.
+    LayoutParameters layoutParameters( size,
+                                       lineBreakInfo.Begin(),
+                                       wordBreakInfo.Begin(),
+                                       numberOfGlyphs,
+                                       glyphs.Begin(),
+                                       glyphsToCharactersMap.Begin(),
+                                       charactersPerGlyph.Begin() );
+
+    // Reserve space to set the positions of the glyphs.
+    Vector<Vector2> glyphPositions;
+    glyphPositions.Resize( numberOfGlyphs );
+
+    Size layoutSize;
+
     // Update the visual model
-    mImpl->mLayoutEngine.UpdateVisualModel( size,
-                                            glyphs,
-                                            glyphsToCharactersMap,
-                                            charactersPerGlyph,
-                                            *mImpl->mVisualModel );
+    viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters,
+                                                   glyphPositions,
+                                                   layoutSize );
+
+    // Sets the positions into the model.
+    mImpl->mVisualModel->SetGlyphPositions( glyphPositions.Begin(),
+                                            numberOfGlyphs );
 
-    viewUpdated = true;
+    // Sets the actual size.
+    mImpl->mVisualModel->SetActualSize( layoutSize );
   }
 
   return viewUpdated;
index 8857203..3fe4439 100644 (file)
@@ -63,19 +63,21 @@ private:
    */
   enum OperationsMask
   {
-    NO_OPERATION      = 0x0,
-    CONVERT_TO_UTF32  = 0x1,
-    GET_SCRIPTS       = 0x2,
-    VALIDATE_FONTS    = 0x4,
-    GET_LINE_BREAKS   = 0x8,
-    GET_WORD_BREAKS   = 0x10,
-    SHAPE_TEXT        = 0x20,
-    GET_GLYPH_METRICS = 0x40,
-    LAYOUT            = 0x80,
-    REORDER           = 0x100,
-    ALIGNMENT         = 0x200,
-    RENDER            = 0x400,
-    ALL_OPERATIONS    = 0xFFF
+    NO_OPERATION       = 0x0000,
+    CONVERT_TO_UTF32   = 0x0001,
+    GET_SCRIPTS        = 0x0002,
+    VALIDATE_FONTS     = 0x0004,
+    GET_LINE_BREAKS    = 0x0008,
+    GET_WORD_BREAKS    = 0x0010,
+    SHAPE_TEXT         = 0x0020,
+    GET_GLYPH_METRICS  = 0x0040,
+    LAYOUT             = 0x0080,
+    UPDATE_ACTUAL_SIZE = 0x0100,
+    UPDATE_POSITIONS   = 0x0200,
+    REORDER            = 0x0400,
+    ALIGNMENT          = 0x0800,
+    RENDER             = 0x1000,
+    ALL_OPERATIONS     = 0xFFFF
   };
 
 public:
@@ -121,7 +123,12 @@ public:
   bool Relayout( const Vector2& size );
 
   /**
+   * @brief Lays-out the text.
    *
+   * GetNaturalSize(), GetHeightForWidth() and Relayout() calls this method.
+   *
+   * @param[in] size A the size of a bounding box to layout text within.
+   * @param[in] operations The layout operations which need to be done.
    */
   bool DoRelayout( const Vector2& size, OperationsMask operations );