Fix text's highlight box. 59/81359/3
authorVictor Cebollada <v.cebollada@samsung.com>
Mon, 25 Jul 2016 09:33:41 +0000 (10:33 +0100)
committerVictor Cebollada <v.cebollada@samsung.com>
Tue, 2 Aug 2016 10:55:28 +0000 (11:55 +0100)
* Fixed a bug when calculating the size of the highlight box.
  It caused the highlight box to be culled.

* Replaces the std::vector<QuadCoordinates> by a Dali::Vector<Vector4>
  and resizes it with the number of quads to avoid reallocations.

Change-Id: Ia3c027c601de9c8c23693a6786fcfdfee57edaeb
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
dali-toolkit/internal/text/decorator/text-decorator.cpp
dali-toolkit/internal/text/decorator/text-decorator.h
dali-toolkit/internal/text/text-controller-impl.cpp

index 58ccff6..da49940 100644 (file)
@@ -104,36 +104,7 @@ const float CURSOR_WIDTH = 1.f; ///< The cursor's width in pixels.
 
 const float POPUP_PADDING = 2.f; ///< Padding space between the highlight box and the text's popup.
 
-/**
- * structure to hold coordinates of each quad, which will make up the mesh.
- */
-struct QuadCoordinates
-{
-  /**
-   * Default constructor
-   */
-  QuadCoordinates()
-  {
-  }
-
-  /**
-   * Constructor
-   * @param[in] x1 left co-ordinate
-   * @param[in] y1 top co-ordinate
-   * @param[in] x2 right co-ordinate
-   * @param[in] y2 bottom co-ordinate
-   */
-  QuadCoordinates(float x1, float y1, float x2, float y2)
-  : min(x1, y1),
-    max(x2, y2)
-  {
-  }
-
-  Dali::Vector2 min;                          ///< top-left (minimum) position of quad
-  Dali::Vector2 max;                          ///< bottom-right (maximum) position of quad
-};
-
-typedef std::vector<QuadCoordinates> QuadContainer;
+typedef Dali::Vector<Dali::Vector4> QuadContainer;
 
 /**
  * @brief Takes a bounding rectangle in the local coordinates of an actor and returns the world coordinates Bounding Box.
@@ -1193,7 +1164,7 @@ struct Decorator::Impl : public ConnectionTracker
       mHighlightActor.SetPosition( mHighlightPosition.x,
                                    mHighlightPosition.y );
 
-      const unsigned int numberOfQuads = mHighlightQuadList.size();
+      const unsigned int numberOfQuads = mHighlightQuadList.Count();
       if( 0u != numberOfQuads )
       {
         // Set the size of the highlighted text to the actor.
@@ -1213,33 +1184,33 @@ struct Decorator::Impl : public ConnectionTracker
         unsigned int v = 0u;
 
         // Traverse all quads.
-        for( std::vector<QuadCoordinates>::iterator it = mHighlightQuadList.begin(),
-               endIt = mHighlightQuadList.end();
+        for( Vector<Vector4>::ConstIterator it = mHighlightQuadList.Begin(),
+               endIt = mHighlightQuadList.End();
              it != endIt;
              ++it, v += 4u )
         {
-          QuadCoordinates& quad = *it;
+          const Vector4& quad = *it;
 
           Vector2 vertex;
 
           // top-left (v+0)
-          vertex.x = quad.min.x - offsetX;
-          vertex.y = quad.min.y - offsetY;
+          vertex.x = quad.x - offsetX;
+          vertex.y = quad.y - offsetY;
           vertices.PushBack( vertex );
 
           // top-right (v+1)
-          vertex.x = quad.max.x - offsetX;
-          vertex.y = quad.min.y - offsetY;
+          vertex.x = quad.z - offsetX;
+          vertex.y = quad.y - offsetY;
           vertices.PushBack( vertex );
 
           // bottom-left (v+2)
-          vertex.x = quad.min.x - offsetX;
-          vertex.y = quad.max.y - offsetY;
+          vertex.x = quad.x - offsetX;
+          vertex.y = quad.w - offsetY;
           vertices.PushBack( vertex );
 
           // bottom-right (v+3)
-          vertex.x = quad.max.x - offsetX;
-          vertex.y = quad.max.y - offsetY;
+          vertex.x = quad.z - offsetX;
+          vertex.y = quad.w - offsetY;
           vertices.PushBack( vertex );
 
           // triangle A (3, 1, 0)
@@ -1274,7 +1245,7 @@ struct Decorator::Impl : public ConnectionTracker
         }
       }
 
-      mHighlightQuadList.clear();
+      mHighlightQuadList.Clear();
 
       if( mHighlightRenderer )
       {
@@ -1932,7 +1903,7 @@ struct Decorator::Impl : public ConnectionTracker
 
   PropertyBuffer      mQuadVertices;
   Geometry            mQuadGeometry;
-  QuadContainer       mHighlightQuadList;         ///< Sub-selections that combine to create the complete selection highlight
+  QuadContainer       mHighlightQuadList;         ///< Sub-selections that combine to create the complete selection highlight.
 
   Vector4             mBoundingBox;               ///< The bounding box in world coords.
   Vector4             mHighlightColor;            ///< Color of the highlight
@@ -2209,9 +2180,9 @@ void Decorator::SetSelectionHandleFlipState( bool indicesSwapped, bool left, boo
   mImpl->mFlipRightSelectionHandleDirection = right;
 }
 
-void Decorator::AddHighlight( float x1, float y1, float x2, float y2 )
+void Decorator::AddHighlight( unsigned int index, const Vector4& quad )
 {
-  mImpl->mHighlightQuadList.push_back( QuadCoordinates(x1, y1, x2, y2) );
+  *( mImpl->mHighlightQuadList.Begin() + index ) = quad;
 }
 
 void Decorator::SetHighLightBox( const Vector2& position, const Size& size )
@@ -2222,10 +2193,15 @@ void Decorator::SetHighLightBox( const Vector2& position, const Size& size )
 
 void Decorator::ClearHighlights()
 {
-  mImpl->mHighlightQuadList.clear();
+  mImpl->mHighlightQuadList.Clear();
   mImpl->mHighlightPosition = Vector2::ZERO;
 }
 
+void Decorator::ResizeHighlightQuads( unsigned int numberOfQuads )
+{
+  mImpl->mHighlightQuadList.Resize( numberOfQuads );
+}
+
 void Decorator::SetHighlightColor( const Vector4& color )
 {
   mImpl->mHighlightColor = color;
index 83388f4..6e7c727 100644 (file)
@@ -437,12 +437,10 @@ public:
   /**
    * @brief Adds a quad to the existing selection highlights. Vertices are in decorator's coordinates.
    *
-   * @param[in] x1 The top-left x position.
-   * @param[in] y1 The top-left y position.
-   * @param[in] x2 The bottom-right x position.
-   * @param[in] y3 The bottom-right y position.
+   * @param[in] index Position in the vector where to add the quad.
+   * @param[in] quad The quad. The 'x' and 'y' coordinates store the min 'x' and min 'y'. The 'z' and 'w' coordinates store the max 'x' and max 'y'.
    */
-  void AddHighlight( float x1, float y1, float x2, float y2 );
+  void AddHighlight( unsigned int index, const Vector4& quad );
 
   /**
    * @brief Sets the min 'x,y' coordinates and the size of the highlighted box.
@@ -462,6 +460,13 @@ public:
   void ClearHighlights();
 
   /**
+   * @brief Reserves space for the highlight quads.
+   *
+   * @param[in] numberOfQuads The expected number of quads.
+   */
+  void ResizeHighlightQuads( unsigned int numberOfQuads );
+
+  /**
    * @brief Sets the selection highlight color.
    *
    * @param[in] color The color to use.
index 9637245..95115da 100644 (file)
@@ -1788,6 +1788,14 @@ void Controller::Impl::RepositionSelectionHandles()
   const Length numberOfCharactersEnd = *( charactersPerGlyphBuffer + glyphEnd );
   bool splitEndGlyph = ( glyphStart != glyphEnd ) && ( numberOfCharactersEnd > 1u ) && HasLigatureMustBreak( mLogicalModel->GetScript( selectionEndMinusOne ) );
 
+  // The number of quads of the selection box.
+  const unsigned int numberOfQuads = 1u + ( glyphEnd - glyphStart ) + ( ( numberOfLines > 1u ) ? 2u * numberOfLines : 0u );
+  mEventData->mDecorator->ResizeHighlightQuads( numberOfQuads );
+
+  // Count the actual number of quads.
+  unsigned int actualNumberOfQuads = 0u;
+  Vector4 quad;
+
   // Traverse the glyphs.
   for( GlyphIndex index = glyphStart; index <= glyphEnd; ++index )
   {
@@ -1811,18 +1819,17 @@ void Controller::Impl::RepositionSelectionHandles()
       // Calculate the number of characters selected.
       const Length numberOfCharacters = ( glyphStart == glyphEnd ) ? ( selectionEnd - selectionStart ) : ( numberOfCharactersStart - interGlyphIndex );
 
-      const float xPosition = lineRun->alignmentOffset + position.x - glyph.xBearing + mScrollPosition.x + glyphAdvance * static_cast<float>( isCurrentRightToLeft ? ( numberOfCharactersStart - interGlyphIndex - numberOfCharacters ) : interGlyphIndex );
-      const float xPositionAdvance = xPosition + static_cast<float>( numberOfCharacters ) * glyphAdvance;
-      const float yPosition = selectionBoxInfo->lineOffset;
+      quad.x = lineRun->alignmentOffset + position.x - glyph.xBearing + mScrollPosition.x + glyphAdvance * static_cast<float>( isCurrentRightToLeft ? ( numberOfCharactersStart - interGlyphIndex - numberOfCharacters ) : interGlyphIndex );
+      quad.y = selectionBoxInfo->lineOffset;
+      quad.z = quad.x + static_cast<float>( numberOfCharacters ) * glyphAdvance;
+      quad.w = selectionBoxInfo->lineOffset + selectionBoxInfo->lineHeight;
 
       // Store the min and max 'x' for each line.
-      selectionBoxInfo->minX = std::min( selectionBoxInfo->minX, xPosition );
-      selectionBoxInfo->maxX = std::max( selectionBoxInfo->maxX, xPositionAdvance );
+      selectionBoxInfo->minX = std::min( selectionBoxInfo->minX, quad.x );
+      selectionBoxInfo->maxX = std::max( selectionBoxInfo->maxX, quad.z );
 
-      mEventData->mDecorator->AddHighlight( xPosition,
-                                            yPosition,
-                                            xPositionAdvance,
-                                            yPosition + selectionBoxInfo->lineHeight );
+      mEventData->mDecorator->AddHighlight( actualNumberOfQuads, quad );
+      ++actualNumberOfQuads;
 
       splitStartGlyph = false;
       continue;
@@ -1843,35 +1850,35 @@ void Controller::Impl::RepositionSelectionHandles()
 
       const Length numberOfCharacters = numberOfCharactersEnd - interGlyphIndex;
 
-      const float xPosition = lineRun->alignmentOffset + position.x - glyph.xBearing + mScrollPosition.x + ( isCurrentRightToLeft ? ( glyphAdvance * static_cast<float>( numberOfCharacters ) ) : 0.f );
-      const float xPositionAdvance = xPosition + static_cast<float>( interGlyphIndex ) * glyphAdvance;
-      const float yPosition = selectionBoxInfo->lineOffset;
+      quad.x = lineRun->alignmentOffset + position.x - glyph.xBearing + mScrollPosition.x + ( isCurrentRightToLeft ? ( glyphAdvance * static_cast<float>( numberOfCharacters ) ) : 0.f );
+      quad.y = selectionBoxInfo->lineOffset;
+      quad.z = quad.x + static_cast<float>( interGlyphIndex ) * glyphAdvance;
+      quad.w = quad.y + selectionBoxInfo->lineHeight;
 
       // Store the min and max 'x' for each line.
-      selectionBoxInfo->minX = std::min( selectionBoxInfo->minX, xPosition );
-      selectionBoxInfo->maxX = std::max( selectionBoxInfo->maxX, xPositionAdvance );
+      selectionBoxInfo->minX = std::min( selectionBoxInfo->minX, quad.x );
+      selectionBoxInfo->maxX = std::max( selectionBoxInfo->maxX, quad.z );
 
-      mEventData->mDecorator->AddHighlight( xPosition,
-                                            yPosition,
-                                            xPositionAdvance,
-                                            yPosition + selectionBoxInfo->lineHeight );
+      mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
+                                            quad );
+      ++actualNumberOfQuads;
 
       splitEndGlyph = false;
       continue;
     }
 
-    const float xPosition = lineRun->alignmentOffset + position.x - glyph.xBearing + mScrollPosition.x;
-    const float xPositionAdvance = xPosition + glyph.advance;
-    const float yPosition = selectionBoxInfo->lineOffset;
+    quad.x = lineRun->alignmentOffset + position.x - glyph.xBearing + mScrollPosition.x;
+    quad.y = selectionBoxInfo->lineOffset;
+    quad.z = quad.x + glyph.advance;
+    quad.w = quad.y + selectionBoxInfo->lineHeight;
 
     // Store the min and max 'x' for each line.
-    selectionBoxInfo->minX = std::min( selectionBoxInfo->minX, xPosition );
-    selectionBoxInfo->maxX = std::max( selectionBoxInfo->maxX, xPositionAdvance );
+    selectionBoxInfo->minX = std::min( selectionBoxInfo->minX, quad.x );
+    selectionBoxInfo->maxX = std::max( selectionBoxInfo->maxX, quad.z );
 
-    mEventData->mDecorator->AddHighlight( xPosition,
-                                          yPosition,
-                                          xPositionAdvance,
-                                          yPosition + selectionBoxInfo->lineHeight );
+    mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
+                                          quad );
+    ++actualNumberOfQuads;
 
     // Whether to retrieve the next line.
     if( index == lastGlyphOfLine )
@@ -1915,7 +1922,7 @@ void Controller::Impl::RepositionSelectionHandles()
     const SelectionBoxInfo& info = *it;
 
     // Update the size of the highlighted text.
-    highLightSize.height += selectionBoxInfo->lineHeight;
+    highLightSize.height += info.lineHeight;
     minHighlightX = std::min( minHighlightX, info.minX );
     maxHighlightX = std::max( maxHighlightX, info.maxX );
   }
@@ -1933,11 +1940,15 @@ void Controller::Impl::RepositionSelectionHandles()
 
     if( boxifyBegin )
     {
+      quad.x = 0.f;
+      quad.y = firstSelectionBoxLineInfo.lineOffset;
+      quad.z = firstSelectionBoxLineInfo.minX;
+      quad.w = firstSelectionBoxLineInfo.lineOffset + firstSelectionBoxLineInfo.lineHeight;
+
       // Boxify at the beginning of the line.
-      mEventData->mDecorator->AddHighlight( 0.f,
-                                            firstSelectionBoxLineInfo.lineOffset,
-                                            firstSelectionBoxLineInfo.minX,
-                                            firstSelectionBoxLineInfo.lineOffset + firstSelectionBoxLineInfo.lineHeight );
+      mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
+                                            quad );
+      ++actualNumberOfQuads;
 
       // Update the size of the highlighted text.
       minHighlightX = 0.f;
@@ -1945,11 +1956,15 @@ void Controller::Impl::RepositionSelectionHandles()
 
     if( boxifyEnd )
     {
+      quad.x = firstSelectionBoxLineInfo.maxX;
+      quad.y = firstSelectionBoxLineInfo.lineOffset;
+      quad.z = mVisualModel->mControlSize.width;
+      quad.w = firstSelectionBoxLineInfo.lineOffset + firstSelectionBoxLineInfo.lineHeight;
+
       // Boxify at the end of the line.
-      mEventData->mDecorator->AddHighlight( firstSelectionBoxLineInfo.maxX,
-                                            firstSelectionBoxLineInfo.lineOffset,
-                                            mVisualModel->mControlSize.width,
-                                            firstSelectionBoxLineInfo.lineOffset + firstSelectionBoxLineInfo.lineHeight );
+      mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
+                                            quad );
+      ++actualNumberOfQuads;
 
       // Update the size of the highlighted text.
       maxHighlightX = mVisualModel->mControlSize.width;
@@ -1965,15 +1980,23 @@ void Controller::Impl::RepositionSelectionHandles()
       {
         const SelectionBoxInfo& info = *it;
 
-        mEventData->mDecorator->AddHighlight( 0.f,
-                                              info.lineOffset,
-                                              info.minX,
-                                              info.lineOffset + info.lineHeight );
+        quad.x = 0.f;
+        quad.y = info.lineOffset;
+        quad.z = info.minX;
+        quad.w = info.lineOffset + info.lineHeight;
+
+        mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
+                                              quad );
+        ++actualNumberOfQuads;
 
-        mEventData->mDecorator->AddHighlight( info.maxX,
-                                              info.lineOffset,
-                                              mVisualModel->mControlSize.width,
-                                              info.lineOffset + info.lineHeight );
+        quad.x = info.maxX;
+        quad.y = info.lineOffset;
+        quad.z = mVisualModel->mControlSize.width;
+        quad.w = info.lineOffset + info.lineHeight;
+
+        mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
+                                              quad );
+        ++actualNumberOfQuads;
       }
 
       // Update the size of the highlighted text.
@@ -1990,11 +2013,15 @@ void Controller::Impl::RepositionSelectionHandles()
 
     if( boxifyBegin )
     {
+      quad.x = 0.f;
+      quad.y = lastSelectionBoxLineInfo.lineOffset;
+      quad.z = lastSelectionBoxLineInfo.minX;
+      quad.w = lastSelectionBoxLineInfo.lineOffset + lastSelectionBoxLineInfo.lineHeight;
+
       // Boxify at the beginning of the line.
-      mEventData->mDecorator->AddHighlight( 0.f,
-                                            lastSelectionBoxLineInfo.lineOffset,
-                                            lastSelectionBoxLineInfo.minX,
-                                            lastSelectionBoxLineInfo.lineOffset + lastSelectionBoxLineInfo.lineHeight );
+      mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
+                                            quad );
+      ++actualNumberOfQuads;
 
       // Update the size of the highlighted text.
       minHighlightX = 0.f;
@@ -2002,17 +2029,24 @@ void Controller::Impl::RepositionSelectionHandles()
 
     if( boxifyEnd )
     {
+      quad.x = lastSelectionBoxLineInfo.maxX;
+      quad.y = lastSelectionBoxLineInfo.lineOffset;
+      quad.z = mVisualModel->mControlSize.width;
+      quad.w = lastSelectionBoxLineInfo.lineOffset + lastSelectionBoxLineInfo.lineHeight;
+
       // Boxify at the end of the line.
-      mEventData->mDecorator->AddHighlight( lastSelectionBoxLineInfo.maxX,
-                                            lastSelectionBoxLineInfo.lineOffset,
-                                            mVisualModel->mControlSize.width,
-                                            lastSelectionBoxLineInfo.lineOffset + lastSelectionBoxLineInfo.lineHeight );
+      mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
+                                            quad );
+      ++actualNumberOfQuads;
 
       // Update the size of the highlighted text.
       maxHighlightX = mVisualModel->mControlSize.width;
     }
   }
 
+  // Set the actual number of quads.
+  mEventData->mDecorator->ResizeHighlightQuads( actualNumberOfQuads );
+
   // Sets the highlight's size and position. In decorator's coords.
   // The highlight's height has been calculated above (before 'boxifying' the highlight).
   highLightSize.width = maxHighlightX - minHighlightX;