Fixing the issue where characters were being drawn at the same location whenever...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-relayouter.cpp
index 2b362c0..227d889 100644 (file)
@@ -61,6 +61,9 @@ Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller)
   VisualModelPtr&   visualModel = model->mVisualModel;
   if(impl.mRecalculateNaturalSize)
   {
+    // Store the pending operations mask so that it can be restored later on with no modifications made on it
+    // while getting the natural size were reflected on the original mask.
+    OperationsMask operationsPendingBackUp = static_cast<OperationsMask>(impl.mOperationsPending);
     // Operations that can be done only once until the text changes.
     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
                                                                           GET_SCRIPTS |
@@ -93,15 +96,6 @@ Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller)
                                            LAYOUT | REORDER),
                naturalSize.GetVectorXY());
 
-    // Do not do again the only once operations.
-    operationsPending = static_cast<OperationsMask>(operationsPending & ~onlyOnceOperations);
-
-    // Do the size related operations again.
-    const OperationsMask sizeOperations = static_cast<OperationsMask>(LAYOUT |
-                                                                      ALIGN |
-                                                                      REORDER);
-    operationsPending                   = static_cast<OperationsMask>(operationsPending | sizeOperations);
-
     // Stores the natural size to avoid recalculate it again
     // unless the text/style changes.
     visualModel->SetNaturalSize(naturalSize.GetVectorXY());
@@ -114,7 +108,8 @@ Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller)
 
     // Restore the actual control's size.
     visualModel->mControlSize = actualControlSize;
-
+    // Restore the previously backed-up pending operations' mask without the only once operations.
+    impl.mOperationsPending = static_cast<OperationsMask>(operationsPendingBackUp & ~onlyOnceOperations);
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize calculated %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z);
   }
   else
@@ -244,6 +239,9 @@ float Controller::Relayouter::GetHeightForWidth(Controller& controller, float wi
      textUpdateInfo.mFullRelayoutNeeded ||
      textUpdateInfo.mClearAll)
   {
+    // Store the pending operations mask so that it can be restored later on with no modifications made on it
+    // while getting the natural size were reflected on the original mask.
+    OperationsMask operationsPendingBackUp = static_cast<OperationsMask>(impl.mOperationsPending);
     // Operations that can be done only once until the text changes.
     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
                                                                           GET_SCRIPTS |
@@ -275,23 +273,14 @@ float Controller::Relayouter::GetHeightForWidth(Controller& controller, float wi
                                            LAYOUT),
                layoutSize);
 
-    // Do not do again the only once operations.
-    operationsPending = static_cast<OperationsMask>(operationsPending & ~onlyOnceOperations);
-
-    // Do the size related operations again.
-    const OperationsMask sizeOperations = static_cast<OperationsMask>(LAYOUT |
-                                                                      ALIGN |
-                                                                      REORDER);
-
-    operationsPending = static_cast<OperationsMask>(operationsPending | sizeOperations);
-
     // Clear the update info. This info will be set the next time the text is updated.
     textUpdateInfo.Clear();
     textUpdateInfo.mClearAll = true;
 
     // Restore the actual control's width.
     visualModel->mControlSize.width = actualControlWidth;
-
+    // Restore the previously backed-up pending operations' mask without the only once operations.
+    impl.mOperationsPending = static_cast<OperationsMask>(operationsPendingBackUp & ~onlyOnceOperations);
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth calculated %f\n", layoutSize.height);
   }
   else
@@ -636,14 +625,29 @@ bool Controller::Relayouter::DoRelayout(Controller& controller, const Size& size
 
 void Controller::Relayouter::CalculateVerticalOffset(Controller& controller, const Size& controlSize)
 {
-  Controller::Impl& impl       = *controller.mImpl;
-  ModelPtr&         model      = impl.mModel;
-  Size              layoutSize = model->mVisualModel->GetLayoutSize();
+  Controller::Impl& impl          = *controller.mImpl;
+  ModelPtr&         model         = impl.mModel;
+  VisualModelPtr&   visualModel   = model->mVisualModel;
+  Size              layoutSize    = model->mVisualModel->GetLayoutSize();
+  Size              oldLayoutSize = layoutSize;
+  float             offsetY       = 0.f;
+  bool              needRecalc    = false;
+  float             defaultFontLineHeight = impl.GetDefaultFontLineHeight();
 
   if(fabsf(layoutSize.height) < Math::MACHINE_EPSILON_1000)
   {
     // Get the line height of the default font.
-    layoutSize.height = impl.GetDefaultFontLineHeight();
+    layoutSize.height = defaultFontLineHeight;
+  }
+
+  // Whether the text control is editable
+  const bool isEditable = NULL != impl.mEventData;
+  if (isEditable && layoutSize.height != defaultFontLineHeight)
+  {
+    // This code prevents the wrong positioning of cursor when the layout size is bigger/smaller than defaultFontLineHeight.
+    // This situation occurs when the size of placeholder text is different from the default text.
+    layoutSize.height = defaultFontLineHeight;
+    needRecalc = true;
   }
 
   switch(model->mVerticalAlignment)
@@ -651,19 +655,34 @@ void Controller::Relayouter::CalculateVerticalOffset(Controller& controller, con
     case VerticalAlignment::TOP:
     {
       model->mScrollPosition.y = 0.f;
+      offsetY = 0.f;
       break;
     }
     case VerticalAlignment::CENTER:
     {
       model->mScrollPosition.y = floorf(0.5f * (controlSize.height - layoutSize.height)); // try to avoid pixel alignment.
+      if (needRecalc) offsetY  = floorf(0.5f * (layoutSize.height - oldLayoutSize.height));
       break;
     }
     case VerticalAlignment::BOTTOM:
     {
       model->mScrollPosition.y = controlSize.height - layoutSize.height;
+      if (needRecalc) offsetY  = layoutSize.height - oldLayoutSize.height;
       break;
     }
   }
+
+  if (needRecalc)
+  {
+    // Update glyphPositions according to recalculation.
+    const Length positionCount = visualModel->mGlyphPositions.Count();
+    Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
+    for(Length index = 0u; index < positionCount; index++)
+    {
+      glyphPositions[index].y += offsetY;
+    }
+  }
+
 }
 
 } // namespace Text