X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Fcontroller%2Ftext-controller-impl-model-updater.cpp;h=fb4eb5f2117b6e122940aab25a5270c0341ede5d;hb=HEAD;hp=ff4697b7f2e72183b47e7dc44a713e4d6b451372;hpb=2847a3b93419ff0423fdc5569446bf79247e01bd;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/text/controller/text-controller-impl-model-updater.cpp b/dali-toolkit/internal/text/controller/text-controller-impl-model-updater.cpp index ff4697b..3d579e9 100644 --- a/dali-toolkit/internal/text/controller/text-controller-impl-model-updater.cpp +++ b/dali-toolkit/internal/text/controller/text-controller-impl-model-updater.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,10 @@ #include // EXTERNAL INCLUDES +#include #include +#include +#include // INTERNAL INCLUDES #include @@ -39,6 +42,20 @@ 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); + +#if defined(TRACE_ENABLED) +uint32_t GetMilliSeconds() +{ + // Get the time of a monotonic clock since its epoch. + auto epoch = std::chrono::steady_clock::now().time_since_epoch(); + + auto duration = std::chrono::duration_cast(epoch); + + return static_cast(duration.count()); +} +#endif + // The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B) // based on W3C Recommendations (https://www.w3.org/TR/WCAG20/) constexpr float BRIGHTNESS_THRESHOLD = 0.179f; @@ -66,6 +83,7 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o // Nothing to do if no operations are pending and required. return false; } + DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_MODEL_UPDATE"); Vector& srcCharacters = impl.mModel->mLogicalModel->mText; Vector displayCharacters; @@ -94,32 +112,39 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o impl.CalculateTextUpdateIndices(paragraphCharacters); // Check whether the indices for updating the text is valid - if(numberOfCharacters > 0u && - (impl.mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters || - impl.mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters)) + if(impl.mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters || + impl.mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters) { - std::string currentText; - Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText); - - DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n"); - DALI_LOG_ERROR("Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str()); - - // Dump mTextUpdateInfo - DALI_LOG_ERROR("Dump mTextUpdateInfo:\n"); - DALI_LOG_ERROR(" mTextUpdateInfo.mCharacterIndex = %u\n", impl.mTextUpdateInfo.mCharacterIndex); - DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToRemove); - DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToAdd); - DALI_LOG_ERROR(" mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mPreviousNumberOfCharacters); - DALI_LOG_ERROR(" mTextUpdateInfo.mParagraphCharacterIndex = %u\n", impl.mTextUpdateInfo.mParagraphCharacterIndex); - DALI_LOG_ERROR(" mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mRequestedNumberOfCharacters); - DALI_LOG_ERROR(" mTextUpdateInfo.mStartGlyphIndex = %u\n", impl.mTextUpdateInfo.mStartGlyphIndex); - DALI_LOG_ERROR(" mTextUpdateInfo.mStartLineIndex = %u\n", impl.mTextUpdateInfo.mStartLineIndex); - DALI_LOG_ERROR(" mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", impl.mTextUpdateInfo.mEstimatedNumberOfLines); - DALI_LOG_ERROR(" mTextUpdateInfo.mClearAll = %d\n", impl.mTextUpdateInfo.mClearAll); - DALI_LOG_ERROR(" mTextUpdateInfo.mFullRelayoutNeeded = %d\n", impl.mTextUpdateInfo.mFullRelayoutNeeded); - DALI_LOG_ERROR(" mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", impl.mTextUpdateInfo.mIsLastCharacterNewParagraph); - - return false; + if(numberOfCharacters == 0u) + { + impl.mTextUpdateInfo.Clear(); + impl.mTextUpdateInfo.mClearAll = true; + } + else // numberOfCharacters > 0u + { + std::string currentText; + Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText); + + DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n"); + DALI_LOG_ERROR("Number of characters: %d, current text is: %s paragraphCharacters: %d\n", numberOfCharacters, currentText.c_str(), paragraphCharacters); + + // Dump mTextUpdateInfo + DALI_LOG_ERROR("Dump mTextUpdateInfo:\n"); + DALI_LOG_ERROR(" mTextUpdateInfo.mCharacterIndex = %u\n", impl.mTextUpdateInfo.mCharacterIndex); + DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToRemove); + DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToAdd); + DALI_LOG_ERROR(" mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mPreviousNumberOfCharacters); + DALI_LOG_ERROR(" mTextUpdateInfo.mParagraphCharacterIndex = %u\n", impl.mTextUpdateInfo.mParagraphCharacterIndex); + DALI_LOG_ERROR(" mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mRequestedNumberOfCharacters); + DALI_LOG_ERROR(" mTextUpdateInfo.mStartGlyphIndex = %u\n", impl.mTextUpdateInfo.mStartGlyphIndex); + DALI_LOG_ERROR(" mTextUpdateInfo.mStartLineIndex = %u\n", impl.mTextUpdateInfo.mStartLineIndex); + DALI_LOG_ERROR(" mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", impl.mTextUpdateInfo.mEstimatedNumberOfLines); + DALI_LOG_ERROR(" mTextUpdateInfo.mClearAll = %d\n", impl.mTextUpdateInfo.mClearAll); + DALI_LOG_ERROR(" mTextUpdateInfo.mFullRelayoutNeeded = %d\n", impl.mTextUpdateInfo.mFullRelayoutNeeded); + DALI_LOG_ERROR(" mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", impl.mTextUpdateInfo.mIsLastCharacterNewParagraph); + + return false; + } } startIndex = impl.mTextUpdateInfo.mParagraphCharacterIndex; @@ -146,10 +171,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o // is not shaped together). lineBreakInfo.Resize(numberOfCharacters, TextAbstraction::LINE_NO_BREAK); - SetLineBreakInfo(utf32Characters, - startIndex, - requestedNumberOfCharacters, - lineBreakInfo); + TextAbstraction::Segmentation segmentation = TextAbstraction::Segmentation::Get(); + SetLineBreakInfo(segmentation, utf32Characters, startIndex, requestedNumberOfCharacters, lineBreakInfo); if(impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) @@ -157,6 +180,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o CharacterIndex end = startIndex + requestedNumberOfCharacters; LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + TextAbstraction::Hyphenation hyphenation = TextAbstraction::Hyphenation::Get(); + for(CharacterIndex index = startIndex; index < end; index++) { CharacterIndex wordEnd = index; @@ -170,7 +195,7 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o wordEnd++; } - Vector hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr); + Vector hyphens = GetWordHyphens(hyphenation, utf32Characters.Begin() + index, wordEnd - index, nullptr); for(CharacterIndex i = 0; i < (wordEnd - index); i++) { @@ -237,7 +262,7 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o // Set the normal font and the placeholder font. defaultFontDescription = impl.mFontDefaults->mFontDescription; - if(impl.mTextFitEnabled) + if(impl.mTextFitEnabled || impl.mTextFitArrayEnabled) { defaultPointSize = impl.mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize; } @@ -249,11 +274,13 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o // Validates the fonts. If there is a character with no assigned font it sets a default one. // After this call, fonts are validated. - multilanguageSupport.ValidateFonts(utf32Characters, + multilanguageSupport.ValidateFonts(impl.mFontClient, + utf32Characters, scripts, fontDescriptionRuns, defaultFontDescription, defaultPointSize, + impl.GetFontSizeScale(), startIndex, requestedNumberOfCharacters, validFonts); @@ -269,8 +296,11 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o Vector& bidirectionalInfo = impl.mModel->mLogicalModel->mBidirectionalParagraphInfo; bidirectionalInfo.Reserve(numberOfParagraphs); + TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get(); + // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts. - SetBidirectionalInfo(utf32Characters, + SetBidirectionalInfo(bidirectionalSupport, + utf32Characters, scripts, lineBreakInfo, startIndex, @@ -283,7 +313,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o { // Only set the character directions if there is right to left characters. Vector& directions = impl.mModel->mLogicalModel->mCharacterDirections; - GetCharactersDirection(bidirectionalInfo, + GetCharactersDirection(bidirectionalSupport, + bidirectionalInfo, numberOfCharacters, startIndex, requestedNumberOfCharacters, @@ -292,7 +323,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o // This paragraph has right to left text. Some characters may need to be mirrored. // TODO: consider if the mirrored string can be stored as well. - textMirrored = GetMirroredText(utf32Characters, + textMirrored = GetMirroredText(bidirectionalSupport, + utf32Characters, directions, bidirectionalInfo, startIndex, @@ -314,11 +346,30 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o newParagraphGlyphs.Reserve(numberOfParagraphs); const Length currentNumberOfGlyphs = glyphs.Count(); + +#if defined(TRACE_ENABLED) + uint32_t logThreshold = TextAbstraction::FontClient::GetPerformanceLogThresholdTime(); + bool logEnabled = TextAbstraction::FontClient::IsPerformanceLogEnabled(); + + uint32_t timeStamps[6]; + uint32_t timeStampIndex = 0; + + if(logEnabled) + { + timeStamps[timeStampIndex++] = GetMilliSeconds(); + } +#endif + if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) { const Vector& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters; + + TextAbstraction::Shaping shaping = TextAbstraction::Shaping::Get(); + // Shapes the text. - ShapeText(textToShape, + ShapeText(shaping, + impl.mFontClient, + textToShape, lineBreakInfo, scripts, validFonts, @@ -337,6 +388,13 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o updated = true; } +#if defined(TRACE_ENABLED) + if(logEnabled) + { + timeStamps[timeStampIndex++] = GetMilliSeconds(); + } +#endif + const Length numberOfGlyphs = static_cast(glyphs.Count()) - currentNumberOfGlyphs; if(Controller::NO_OPERATION != (Controller::GET_GLYPH_METRICS & operations)) @@ -357,6 +415,13 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o updated = true; } +#if defined(TRACE_ENABLED) + if(logEnabled) + { + timeStamps[timeStampIndex++] = GetMilliSeconds(); + } +#endif + if((nullptr != impl.mEventData) && impl.mEventData->mPreEditFlag && (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count())) @@ -387,7 +452,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); //Mark-up processor case - if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() || + impl.mModel->mLogicalModel->mUnderlineRunsUpdated) { impl.CopyUnderlinedFromLogicalToVisualModels(false); } @@ -403,13 +469,13 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); Vector4 backgroundColor = impl.mModel->mVisualModel->GetBackgroundColor(); - if(backgroundColor.a == 0) // There is no text background color. + if(Dali::EqualsZero(backgroundColor.a)) // There is no text background color. { // Try use the control's background color. if(nullptr != impl.mEditableControlInterface) { impl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor); - if(backgroundColor.a == 0) // There is no control background color. + if(Dali::EqualsZero(backgroundColor.a)) // There is no control background color. { // Determines black or white color according to text color. // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/) @@ -428,7 +494,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o impl.mModel->mLogicalModel->mColorRuns.PushBack(colorRun); //Mark-up processor case - if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() || + impl.mModel->mLogicalModel->mUnderlineRunsUpdated) { impl.CopyUnderlinedFromLogicalToVisualModels(false); } @@ -443,7 +510,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); //Mark-up processor case - if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() || + impl.mModel->mLogicalModel->mUnderlineRunsUpdated) { impl.CopyUnderlinedFromLogicalToVisualModels(false); } @@ -464,7 +532,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); //Mark-up processor case - if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() || + impl.mModel->mLogicalModel->mUnderlineRunsUpdated) { impl.CopyUnderlinedFromLogicalToVisualModels(false); } @@ -485,7 +554,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); //Mark-up processor case - if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() || + impl.mModel->mLogicalModel->mUnderlineRunsUpdated) { impl.CopyUnderlinedFromLogicalToVisualModels(false); } @@ -506,7 +576,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); //Mark-up processor case - if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() || + impl.mModel->mLogicalModel->mUnderlineRunsUpdated) { impl.CopyUnderlinedFromLogicalToVisualModels(false); } @@ -527,7 +598,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); //Mark-up processor case - if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() || + impl.mModel->mLogicalModel->mUnderlineRunsUpdated) { impl.CopyUnderlinedFromLogicalToVisualModels(false); } @@ -544,6 +616,13 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o updated = true; } +#if defined(TRACE_ENABLED) + if(logEnabled) + { + timeStamps[timeStampIndex++] = GetMilliSeconds(); + } +#endif + if(Controller::NO_OPERATION != (Controller::COLOR & operations)) { // Set the color runs in glyphs. @@ -569,13 +648,23 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o updated = true; } +#if defined(TRACE_ENABLED) + if(logEnabled) + { + timeStamps[timeStampIndex++] = GetMilliSeconds(); + } +#endif + if((Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) && !((nullptr != impl.mEventData) && impl.mEventData->mPreEditFlag && (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count()))) { //Mark-up processor case - if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() || + impl.mModel->mLogicalModel->mUnderlineRunsUpdated || + impl.mModel->mLogicalModel->mCharacterSpacingRunsUpdated || + impl.mModel->mLogicalModel->mStrikethroughRunsUpdated) { impl.CopyUnderlinedFromLogicalToVisualModels(true); impl.CopyStrikethroughFromLogicalToVisualModels(); @@ -585,6 +674,26 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o updated = true; } +#if defined(TRACE_ENABLED) + if(logEnabled) + { + timeStamps[timeStampIndex++] = GetMilliSeconds(); + uint32_t timeShape = timeStamps[1] - timeStamps[0]; + uint32_t timeGlyph = timeStamps[2] - timeStamps[1]; + uint32_t timePreedit = timeStamps[3] - timeStamps[2]; + uint32_t timeColor = timeStamps[4] - timeStamps[3]; + uint32_t timeCopy = timeStamps[5] - timeStamps[4]; + + if(timeStamps[5] - timeStamps[0] > logThreshold) + { + std::string currentText; + Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText); + DALI_LOG_DEBUG_INFO("DALI_TEXT_MODEL_UPDATE shape:%u ms, glyph:%u ms, preedit:%u ms, color:%u ms, copy:%u ms\n", timeShape, timeGlyph, timePreedit, timeColor, timeCopy); + DALI_LOG_DEBUG_INFO("DALI_TEXT_MODEL_UPDATE chars:%d, text:%s\n", numberOfCharacters, currentText.c_str()); + } + } +#endif + // The estimated number of lines. Used to avoid reallocations when layouting. impl.mTextUpdateInfo.mEstimatedNumberOfLines = std::max(impl.mModel->mVisualModel->mLines.Count(), impl.mModel->mLogicalModel->mParagraphInfo.Count());