// 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
-#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
#include <dali-toolkit/internal/text/controller/text-controller-event-handler.h>
#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
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);
+
constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
float ConvertToEven(float value)
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.
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
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 currentFitPointSize = impl.mFontDefaults->mFitPointSize;
model->mElideEnabled = false;
- Vector<float> pointSizeArray;
// check zero value
if(pointInterval < 1.f)
{
impl.mTextFitStepSize = pointInterval = 1.0f;
}
+ uint32_t pointSizeRange = static_cast<uint32_t>(ceil((maxPointSize - minPointSize) / pointInterval));
- pointSizeArray.Reserve(static_cast<unsigned int>(ceil((maxPointSize - minPointSize) / pointInterval)));
-
- for(float i = minPointSize; i < maxPointSize; i += pointInterval)
+ // Ensure minPointSize + pointSizeRange * pointInverval >= maxPointSize
+ while(minPointSize + static_cast<float>(pointSizeRange) * pointInterval < maxPointSize)
{
- pointSizeArray.PushBack(i);
+ ++pointSizeRange;
}
- pointSizeArray.PushBack(maxPointSize);
-
- int bestSizeIndex = 0;
- int min = bestSizeIndex + 1;
- int max = pointSizeArray.Size() - 1;
- while(min <= max)
+ uint32_t bestSizeIndex = 0;
+ uint32_t minIndex = bestSizeIndex + 1u;
+ uint32_t maxIndex = pointSizeRange + 1u;
+
+ bool bestSizeUpdatedLatest = false;
+ // Find best size as binary search.
+ // Range format as [l r). (left closed, right opened)
+ // It mean, we already check all i < l is valid, and r <= i is invalid.
+ // Below binary search will check m = (l+r)/2 point.
+ // Search area sperate as [l m) or [m+1 r)
+ //
+ // Basically, we can assume that 0 (minPointSize) is always valid.
+ // Now, we will check [1 pointSizeRange] range s.t. pointSizeRange mean the maxPointSize
+ while(minIndex < maxIndex)
{
- int destI = (min + max) / 2;
+ uint32_t testIndex = minIndex + ((maxIndex - minIndex) >> 1u);
+ const float testPointSize = std::min(maxPointSize, minPointSize + static_cast<float>(testIndex) * pointInterval);
- if(CheckForTextFit(controller, pointSizeArray[destI], layoutSize))
+ if(CheckForTextFit(controller, testPointSize, layoutSize))
{
- bestSizeIndex = min;
- min = destI + 1;
+ bestSizeUpdatedLatest = true;
+
+ bestSizeIndex = testIndex;
+ minIndex = testIndex + 1u;
}
else
{
- max = destI - 1;
- bestSizeIndex = max;
+ bestSizeUpdatedLatest = false;
+ maxIndex = testIndex;
}
}
+ const float bestPointSize = std::min(maxPointSize, minPointSize + static_cast<float>(bestSizeIndex) * pointInterval);
+
+ // Best point size was not updated. re-run so the TextFit should be fitted really.
+ if(!bestSizeUpdatedLatest)
+ {
+ CheckForTextFit(controller, bestPointSize, layoutSize);
+ }
model->mElideEnabled = actualellipsis;
- if(currentFitPointSize != pointSizeArray[bestSizeIndex])
+ if(!Dali::Equals(currentFitPointSize, bestPointSize))
{
impl.mTextFitChanged = true;
}
- impl.mFontDefaults->mFitPointSize = pointSizeArray[bestSizeIndex];
+ impl.mFontDefaults->mFitPointSize = bestPointSize;
impl.mFontDefaults->sizeDefined = true;
impl.ClearFontData();
}
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);
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;
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(gTraceFilter, "DALI_TEXT_DORELAYOUT");
bool viewUpdated(false);
// Calculate the operations to be done.
// 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,
elideTextEnabled,
isAutoScrollEnabled,
isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
ellipsisPosition);
impl.mIsAutoScrollEnabled = isAutoScrollEnabled;
// 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.