Add GetHeightForWidth for text visual model
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / controller / text-controller-relayouter.cpp
index f95019a..fafff2f 100644 (file)
@@ -20,6 +20,8 @@
 
 // EXTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
+#include <dali/integration-api/trace.h>
+#include <dali/public-api/math/math-utils.h>
 #include <limits>
 
 // INTERNAL INCLUDES
@@ -33,6 +35,9 @@ namespace
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
 #endif
 
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_TEXT_PERFORMANCE_MARKER, false);
+DALI_INIT_TRACE_FILTER(gTraceFilter2, DALI_TRACE_PERFORMANCE_MARKER, false);
+
 constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
 
 float ConvertToEven(float value)
@@ -95,6 +100,13 @@ Size Controller::Relayouter::CalculateLayoutSizeOnRequiredControllerSize(Control
 
   if(!isEditable)
   {
+    if(NO_OPERATION != (VALIDATE_FONTS & operationsPending) &&
+       textUpdateInfo.mCharacterIndex == static_cast<CharacterIndex>(-1))
+    {
+      impl.ClearFontData();
+      updateInfoCharIndexBackup = textUpdateInfo.mCharacterIndex;
+    }
+
     impl.UpdateModel(onlyOnceOperations);
 
     // Layout the text for the new width.
@@ -156,6 +168,7 @@ Size Controller::Relayouter::CalculateLayoutSizeOnRequiredControllerSize(Control
 Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller)
 {
   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetNaturalSize\n");
+  DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_GET_NATURAL_SIZE");
   Vector3 naturalSizeVec3;
 
   // Make sure the model is up-to-date before layouting
@@ -230,7 +243,7 @@ bool Controller::Relayouter::CheckForTextFit(Controller& controller, float point
   textUpdateInfo.Clear();
   textUpdateInfo.mClearAll = true;
 
-  if(textSize.width >= layoutSize.width || textSize.height >= layoutSize.height)
+  if(textSize.width > layoutSize.width || textSize.height > layoutSize.height)
   {
     return false;
   }
@@ -244,13 +257,17 @@ void Controller::Relayouter::FitPointSizeforLayout(Controller& controller, const
   const OperationsMask operations = impl.mOperationsPending;
   if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations) || impl.mTextFitContentSize != layoutSize)
   {
+    DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_FIT_LAYOUT");
     ModelPtr& model = impl.mModel;
 
-    bool  actualellipsis      = model->mElideEnabled;
-    float minPointSize        = impl.mTextFitMinSize;
-    float maxPointSize        = impl.mTextFitMaxSize;
-    float pointInterval       = impl.mTextFitStepSize;
-    float currentFitPointSize = impl.mFontDefaults->mFitPointSize;
+    bool  actualellipsis         = model->mElideEnabled;
+    float minPointSize           = impl.mTextFitMinSize;
+    float maxPointSize           = impl.mTextFitMaxSize;
+    float pointInterval          = impl.mTextFitStepSize;
+    float currentFitPointSize    = impl.mFontDefaults->mFitPointSize;
+    float currentDefaultLineSize = impl.mLayoutEngine.GetDefaultLineSize();
+    // Instead of using the LineSize of the current TextLabel, the LineSize set in TextFit is used.
+    impl.SetDefaultLineSize(impl.mTextFitLineSize);
 
     model->mElideEnabled = false;
 
@@ -307,10 +324,12 @@ void Controller::Relayouter::FitPointSizeforLayout(Controller& controller, const
     }
 
     model->mElideEnabled = actualellipsis;
-    if(currentFitPointSize != bestPointSize)
+    if(!Dali::Equals(currentFitPointSize, bestPointSize))
     {
       impl.mTextFitChanged = true;
     }
+    // Revert back to the original TextLabel LineSize.
+    impl.SetDefaultLineSize(currentDefaultLineSize);
     impl.mFontDefaults->mFitPointSize = bestPointSize;
     impl.mFontDefaults->sizeDefined   = true;
     impl.ClearFontData();
@@ -320,6 +339,7 @@ void Controller::Relayouter::FitPointSizeforLayout(Controller& controller, const
 float Controller::Relayouter::GetHeightForWidth(Controller& controller, float width)
 {
   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetHeightForWidth %p width %f\n", &controller, width);
+  DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_GET_HEIGHT_FOR_WIDTH");
 
   // Make sure the model is up-to-date before layouting
   EventHandler::ProcessModifyEvents(controller);
@@ -329,9 +349,10 @@ float Controller::Relayouter::GetHeightForWidth(Controller& controller, float wi
   VisualModelPtr&   visualModel    = model->mVisualModel;
   TextUpdateInfo&   textUpdateInfo = impl.mTextUpdateInfo;
 
-  Size layoutSize;
+  // Get cached value.
+  Size layoutSize = visualModel->GetHeightForWidth();
 
-  if(fabsf(width - visualModel->mControlSize.width) > Math::MACHINE_EPSILON_1000 ||
+  if(fabsf(width - layoutSize.width) > Math::MACHINE_EPSILON_1000 ||
      textUpdateInfo.mFullRelayoutNeeded ||
      textUpdateInfo.mClearAll)
   {
@@ -341,11 +362,15 @@ float Controller::Relayouter::GetHeightForWidth(Controller& controller, float wi
 
     layoutSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeRequestedWidthAndMaxHeight, requestedOperationsMask);
 
+    // The calculated layout width may not be the same as the requested width.
+    // For cache efficiency, the requested width is stored.
+    layoutSize.width = width;
+    visualModel->SetHeightForWidth(layoutSize);
+
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth calculated %f\n", layoutSize.height);
   }
   else
   {
-    layoutSize = visualModel->GetLayoutSize();
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth cached %f\n", layoutSize.height);
   }
 
@@ -360,6 +385,7 @@ Controller::UpdateTextType Controller::Relayouter::Relayout(Controller& controll
   TextUpdateInfo&   textUpdateInfo = impl.mTextUpdateInfo;
 
   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", &controller, size.width, size.height, impl.mIsAutoScrollEnabled ? "true" : "false");
+  DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_RELAYOUT");
 
   UpdateTextType updateTextType = NONE_UPDATED;
 
@@ -537,6 +563,7 @@ Controller::UpdateTextType Controller::Relayouter::Relayout(Controller& controll
 bool Controller::Relayouter::DoRelayout(Controller::Impl& impl, const Size& size, OperationsMask operationsRequired, Size& layoutSize)
 {
   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::Relayouter::DoRelayout %p size %f,%f\n", &impl, size.width, size.height);
+  DALI_TRACE_SCOPE(gTraceFilter2, "DALI_TEXT_DORELAYOUT");
   bool viewUpdated(false);
 
   // Calculate the operations to be done.
@@ -641,6 +668,11 @@ bool Controller::Relayouter::DoRelayout(Controller::Impl& impl, const Size& size
     // Update the visual model.
     bool isAutoScrollEnabled            = impl.mIsAutoScrollEnabled;
     bool isAutoScrollMaxTextureExceeded = impl.mIsAutoScrollMaxTextureExceeded;
+    bool isHiddenInputEnabled           = false;
+    if(impl.mHiddenInput && impl.mEventData != nullptr && impl.mHiddenInput->GetHideMode() != Toolkit::HiddenInput::Mode::HIDE_NONE)
+    {
+      isHiddenInputEnabled = true;
+    }
 
     Size newLayoutSize;
     viewUpdated               = impl.mLayoutEngine.LayoutText(layoutParameters,
@@ -648,6 +680,7 @@ bool Controller::Relayouter::DoRelayout(Controller::Impl& impl, const Size& size
                                                 elideTextEnabled,
                                                 isAutoScrollEnabled,
                                                 isAutoScrollMaxTextureExceeded,
+                                                isHiddenInputEnabled,
                                                 ellipsisPosition);
     impl.mIsAutoScrollEnabled = isAutoScrollEnabled;
 
@@ -837,7 +870,7 @@ void Controller::Relayouter::CalculateVerticalOffset(Controller::Impl& impl, con
 
   // Whether the text control is editable
   const bool isEditable = NULL != impl.mEventData;
-  if(isEditable && layoutSize.height != defaultFontLineHeight && impl.IsShowingPlaceholderText())
+  if(isEditable && !Dali::Equals(layoutSize.height, defaultFontLineHeight) && impl.IsShowingPlaceholderText())
   {
     // 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.