+void Controller::Relayouter::FitArrayPointSizeforLayout(Controller& controller, const Size& layoutSize)
+{
+ Controller::Impl& impl = *controller.mImpl;
+
+ const OperationsMask operations = impl.mOperationsPending;
+ if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations) || impl.mTextFitContentSize != layoutSize)
+ {
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_FIT_ARRAY_LAYOUT");
+ std::vector<Toolkit::DevelTextLabel::FitOption> fitOptions = impl.mTextFitArray;
+ int numberOfFitOptions = static_cast<int>(fitOptions.size());
+ if(numberOfFitOptions == 0)
+ {
+ DALI_LOG_ERROR("fitOptions is empty\n");
+ return;
+ }
+
+ ModelPtr& model = impl.mModel;
+ bool actualellipsis = model->mElideEnabled;
+ model->mElideEnabled = false;
+
+ // Sort in ascending order by PointSize.
+ std::sort(fitOptions.begin(), fitOptions.end(), compareByPointSize);
+
+ // Decide whether to use binary search.
+ // If MinLineSize is not sorted in ascending order,
+ // binary search cannot guarantee that it will always find the best value.
+ bool binarySearch = true;
+ float prevMinLineSize = 0.0f;
+ for(Toolkit::DevelTextLabel::FitOption& option : fitOptions)
+ {
+ float optionMinLineSize = option.GetMinLineSize();
+ if(prevMinLineSize > optionMinLineSize)
+ {
+ binarySearch = false;
+ break;
+ }
+ prevMinLineSize = optionMinLineSize;
+ }
+
+ // Set the first FitOption(Minimum PointSize) to the best value.
+ // If the search does not find an optimal value, the minimum PointSize will be used to text fit.
+ Toolkit::DevelTextLabel::FitOption firstOption = fitOptions.front();
+ bool bestSizeUpdatedLatest = false;
+ float bestPointSize = firstOption.GetPointSize();
+ float bestMinLineSize = firstOption.GetMinLineSize();
+
+ if(binarySearch)
+ {
+ int left = 0u;
+ int right = numberOfFitOptions - 1;
+
+ while (left <= right)
+ {
+ int mid = left + (right - left) / 2;
+ Toolkit::DevelTextLabel::FitOption option = fitOptions[mid];
+ float testPointSize = option.GetPointSize();
+ float testMinLineSize = option.GetMinLineSize();
+ impl.SetDefaultLineSize(testMinLineSize);
+
+ if(CheckForTextFit(controller, testPointSize, layoutSize))
+ {
+ bestSizeUpdatedLatest = true;
+ bestPointSize = testPointSize;
+ bestMinLineSize = testMinLineSize;
+ left = mid + 1;
+ }
+ else
+ {
+ bestSizeUpdatedLatest = false;
+ right = mid - 1;
+ }
+ }
+ }
+ else
+ {
+ // If binary search is not possible, search sequentially starting from the largest PointSize.
+ for(auto it = fitOptions.rbegin(); it != fitOptions.rend(); ++it)
+ {
+ Toolkit::DevelTextLabel::FitOption option = *it;
+ float testPointSize = option.GetPointSize();
+ float testMinLineSize = option.GetMinLineSize();
+ impl.SetDefaultLineSize(testMinLineSize);
+
+ if(CheckForTextFit(controller, testPointSize, layoutSize))
+ {
+ bestSizeUpdatedLatest = true;
+ bestPointSize = testPointSize;
+ bestMinLineSize = testMinLineSize;
+ break;
+ }
+ else
+ {
+ bestSizeUpdatedLatest = false;
+ }
+ }
+ }
+
+ // Best point size was not updated. re-run so the TextFit should be fitted really.
+ if(!bestSizeUpdatedLatest)
+ {
+ impl.SetDefaultLineSize(bestMinLineSize);
+ CheckForTextFit(controller, bestPointSize, layoutSize);
+ }
+
+ model->mElideEnabled = actualellipsis;
+ impl.mFontDefaults->mFitPointSize = bestPointSize;
+ impl.mFontDefaults->sizeDefined = true;
+ impl.ClearFontData();
+ }
+}
+