Merge "TextField is re-laied out after its properties are changed." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / layouts / layout-engine.cpp
index 4f9876c..5594c01 100755 (executable)
@@ -117,26 +117,31 @@ struct Engine::Impl
   /**
    * @brief Updates the line ascender and descender with the metrics of a new font.
    *
-   * @param[in] fontId The id of the new font.
+   * @param[in] glyphMetrics The metrics of the new font.
    * @param[in,out] lineLayout The line layout.
    */
-  void UpdateLineHeight( FontId fontId, LineLayout& lineLayout )
+  void UpdateLineHeight( const GlyphMetrics& glyphMetrics, LineLayout& lineLayout )
   {
     Text::FontMetrics fontMetrics;
-    mMetrics->GetFontMetrics( fontId, fontMetrics );
-
-    // Sets the maximum ascender.
-    if( fontMetrics.ascender > lineLayout.ascender )
+    if( 0u != glyphMetrics.fontId )
     {
-      lineLayout.ascender = fontMetrics.ascender;
+      mMetrics->GetFontMetrics( glyphMetrics.fontId, fontMetrics );
     }
-
-    // Sets the minimum descender.
-    if( fontMetrics.descender < lineLayout.descender )
+    else
     {
-      lineLayout.descender = fontMetrics.descender;
+      fontMetrics.ascender = glyphMetrics.fontHeight;
+      fontMetrics.descender = 0.f;
+      fontMetrics.height = fontMetrics.ascender;
+      fontMetrics.underlinePosition = 0.f;
+      fontMetrics.underlineThickness = 1.f;
     }
 
+    // Sets the maximum ascender.
+    lineLayout.ascender = std::max( lineLayout.ascender, fontMetrics.ascender );
+
+    // Sets the minimum descender.
+    lineLayout.descender = std::min( lineLayout.descender, fontMetrics.descender );
+
     // set the line spacing
     lineLayout.lineSpacing = mDefaultLineSpacing;
   }
@@ -158,22 +163,18 @@ struct Engine::Impl
     {
       lineLayout.length += lineLayout.wsLengthEndOfLine;
 
-      lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
+    lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
     }
     else
     {
       lineLayout.wsLengthEndOfLine += tmpLineLayout.wsLengthEndOfLine;
     }
 
-    if( tmpLineLayout.ascender > lineLayout.ascender )
-    {
-      lineLayout.ascender = tmpLineLayout.ascender;
-    }
+    // Sets the maximum ascender.
+    lineLayout.ascender = std::max( lineLayout.ascender, tmpLineLayout.ascender );
 
-    if( tmpLineLayout.descender < lineLayout.descender )
-    {
-      lineLayout.descender = tmpLineLayout.descender;
-    }
+    // Sets the minimum descender.
+    lineLayout.descender = std::min( lineLayout.descender, tmpLineLayout.descender );
   }
 
   /**
@@ -239,7 +240,7 @@ struct Engine::Impl
 
     // Calculate the line height if there is no characters.
     FontId lastFontId = glyphMetrics.fontId;
-    UpdateLineHeight( lastFontId, tmpLineLayout );
+    UpdateLineHeight( glyphMetrics, tmpLineLayout );
 
     bool oneWordLaidOut = false;
 
@@ -266,7 +267,7 @@ struct Engine::Impl
       // If it's different the ascender and descender need to be updated.
       if( lastFontId != glyphMetrics.fontId )
       {
-        UpdateLineHeight( glyphMetrics.fontId, tmpLineLayout );
+        UpdateLineHeight( glyphMetrics, tmpLineLayout );
         lastFontId = glyphMetrics.fontId;
       }
 
@@ -555,6 +556,7 @@ struct Engine::Impl
    * @param[in,out] numberOfLines The number of laid-out lines.
    * @param[in] penY The vertical layout position.
    * @param[in] currentParagraphDirection The current paragraph's direction.
+   * @param[in,out] isAutoScrollEnabled If the isAutoScrollEnabled is true and the height of the text exceeds the boundaries of the control the text is elided and the isAutoScrollEnabled is set to false to disable the autoscroll
    *
    * return Whether the line is ellipsized.
    */
@@ -565,14 +567,17 @@ struct Engine::Impl
                      Vector2* glyphPositionsBuffer,
                      Length& numberOfLines,
                      float penY,
-                     CharacterDirection currentParagraphDirection )
+                     CharacterDirection currentParagraphDirection,
+                     bool& isAutoScrollEnabled )
   {
-    const bool ellipsis = ( ( penY - layout.descender > layoutParameters.boundingBox.height ) ||
-                            ( ( mLayout == SINGLE_LINE_BOX ) &&
-                              ( layout.extraBearing + layout.length + layout.extraWidth > layoutParameters.boundingBox.width ) ) );
+    const bool ellipsis = isAutoScrollEnabled ? ( penY - layout.descender > layoutParameters.boundingBox.height ) :
+                                                ( ( penY - layout.descender > layoutParameters.boundingBox.height ) ||
+                                                  ( ( mLayout == SINGLE_LINE_BOX ) &&
+                                                    ( layout.length > layoutParameters.boundingBox.width ) ) );
 
     if( ellipsis )
     {
+      isAutoScrollEnabled = false;
       // Do not layout more lines if ellipsis is enabled.
 
       // The last line needs to be completely filled with characters.
@@ -609,7 +614,7 @@ struct Engine::Impl
       lineRun->characterRun.characterIndex = ellipsisLayout.characterIndex;
       lineRun->characterRun.numberOfCharacters = ellipsisLayout.numberOfCharacters;
       lineRun->width = ellipsisLayout.length;
-      lineRun->extraLength =  ( ellipsisLayout.wsLengthEndOfLine > 0.f ) ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.extraWidth : 0.f;
+      lineRun->extraLength =  std::ceil( ( ellipsisLayout.wsLengthEndOfLine > 0.f ) ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.extraWidth : 0.f );
       lineRun->ascender = ellipsisLayout.ascender;
       lineRun->descender = ellipsisLayout.descender;
       lineRun->direction = !RTL;
@@ -675,8 +680,12 @@ struct Engine::Impl
     else
     {
       lineRun.width = layout.extraBearing + layout.length + layout.extraWidth;
-      lineRun.extraLength = ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f;
+      lineRun.extraLength = std::ceil( ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f );
     }
+
+    // Rounds upward to avoid a non integer size.
+    lineRun.width = std::ceil( lineRun.width );
+
     lineRun.ascender = layout.ascender;
     lineRun.descender = layout.descender;
     lineRun.direction = !RTL;
@@ -712,7 +721,10 @@ struct Engine::Impl
     const GlyphInfo& glyphInfo = *( layoutParameters.glyphsBuffer + layoutParameters.totalNumberOfGlyphs - 1u );
 
     Text::FontMetrics fontMetrics;
-    mMetrics->GetFontMetrics( glyphInfo.fontId, fontMetrics );
+    if( 0u != glyphInfo.fontId )
+    {
+      mMetrics->GetFontMetrics( glyphInfo.fontId, fontMetrics );
+    }
 
     LineRun& lineRun = *( linesBuffer + numberOfLines );
     ++numberOfLines;
@@ -791,7 +803,8 @@ struct Engine::Impl
                    Vector<Vector2>& glyphPositions,
                    Vector<LineRun>& lines,
                    Size& layoutSize,
-                   bool elideTextEnabled )
+                   bool elideTextEnabled,
+                   bool& isAutoScrollEnabled )
   {
     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 );
@@ -827,6 +840,9 @@ struct Engine::Impl
       UpdateLayoutSize( lines,
                         layoutSize );
 
+      // Rounds upward to avoid a non integer size.
+      layoutSize.height = std::ceil( layoutSize.height );
+
       // Nothing else do if there are no glyphs to layout.
       return false;
     }
@@ -905,6 +921,10 @@ struct Engine::Impl
         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText width too small!\n\n" );
 
         lines.Resize( numberOfLines );
+
+        // Rounds upward to avoid a non integer size.
+        layoutSize.height = std::ceil( layoutSize.height );
+
         return false;
       }
 
@@ -925,7 +945,8 @@ struct Engine::Impl
                                  glyphPositionsBuffer,
                                  numberOfLines,
                                  penY,
-                                 currentParagraphDirection );
+                                 currentParagraphDirection,
+                                 isAutoScrollEnabled );
       }
 
       if( ellipsis )
@@ -1035,6 +1056,9 @@ struct Engine::Impl
       lines.Resize( numberOfLines );
     }
 
+    // Rounds upward to avoid a non integer size.
+    layoutSize.height = std::ceil( layoutSize.height );
+
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText\n\n" );
 
     return true;
@@ -1291,13 +1315,15 @@ bool Engine::LayoutText( const Parameters& layoutParameters,
                          Vector<Vector2>& glyphPositions,
                          Vector<LineRun>& lines,
                          Size& layoutSize,
-                         bool elideTextEnabled )
+                         bool elideTextEnabled,
+                         bool& isAutoScrollEnabled )
 {
   return mImpl->LayoutText( layoutParameters,
                             glyphPositions,
                             lines,
                             layoutSize,
-                            elideTextEnabled );
+                            elideTextEnabled,
+                            isAutoScrollEnabled );
 }
 
 void Engine::ReLayoutRightToLeftLines( const Parameters& layoutParameters,