2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/internal/text/text-controller-impl-model-updater.h>
22 #include <dali/integration-api/debug.h>
25 #include <dali-toolkit/internal/text/bidirectional-support.h>
26 #include <dali-toolkit/internal/text/character-set-conversion.h>
27 #include <dali-toolkit/internal/text/color-segmentation.h>
28 #include <dali-toolkit/internal/text/hyphenator.h>
29 #include <dali-toolkit/internal/text/multi-language-support.h>
30 #include <dali-toolkit/internal/text/segmentation.h>
31 #include <dali-toolkit/internal/text/shaper.h>
32 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
34 namespace Dali::Toolkit::Text
38 #if defined(DEBUG_ENABLED)
39 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
42 // The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B)
43 // based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
44 constexpr float BRIGHTNESS_THRESHOLD = 0.179f;
45 constexpr float CONSTANT_R = 0.2126f;
46 constexpr float CONSTANT_G = 0.7152f;
47 constexpr float CONSTANT_B = 0.0722f;
48 constexpr Dali::Vector4 BLACK(0.f, 0.f, 0.f, 1.f);
49 constexpr Dali::Vector4 WHITE(1.f, 1.f, 1.f, 1.f);
50 constexpr Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f);
51 constexpr Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f);
52 constexpr Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f);
53 constexpr Dali::Vector4 BACKGROUND_SUB6(1.f, 0.5f, 0.5f, 1.f);
54 constexpr Dali::Vector4 BACKGROUND_SUB7(1.f, 0.8f, 0.8f, 1.f);
57 bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask operationsRequired)
59 DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel\n");
61 // Calculate the operations to be done.
62 const OperationsMask operations = static_cast<OperationsMask>(impl.mOperationsPending & operationsRequired);
64 if(Controller::NO_OPERATION == operations)
66 // Nothing to do if no operations are pending and required.
70 Vector<Character>& srcCharacters = impl.mModel->mLogicalModel->mText;
71 Vector<Character> displayCharacters;
72 bool useHiddenText = false;
73 if(impl.mHiddenInput && impl.mEventData != nullptr && !impl.mEventData->mIsShowingPlaceholderText)
75 impl.mHiddenInput->Substitute(srcCharacters, displayCharacters);
79 Vector<Character>& utf32Characters = useHiddenText ? displayCharacters : srcCharacters;
80 const Length numberOfCharacters = utf32Characters.Count();
82 // Index to the first character of the first paragraph to be updated.
83 CharacterIndex startIndex = 0u;
84 // Number of characters of the paragraphs to be removed.
85 Length paragraphCharacters = 0u;
87 impl.CalculateTextUpdateIndices(paragraphCharacters);
89 // Check whether the indices for updating the text is valid
90 if(numberOfCharacters > 0u &&
91 (impl.mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters ||
92 impl.mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters))
94 std::string currentText;
95 Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText);
97 DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n");
98 DALI_LOG_ERROR("Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str());
100 // Dump mTextUpdateInfo
101 DALI_LOG_ERROR("Dump mTextUpdateInfo:\n");
102 DALI_LOG_ERROR(" mTextUpdateInfo.mCharacterIndex = %u\n", impl.mTextUpdateInfo.mCharacterIndex);
103 DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToRemove);
104 DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToAdd);
105 DALI_LOG_ERROR(" mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mPreviousNumberOfCharacters);
106 DALI_LOG_ERROR(" mTextUpdateInfo.mParagraphCharacterIndex = %u\n", impl.mTextUpdateInfo.mParagraphCharacterIndex);
107 DALI_LOG_ERROR(" mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mRequestedNumberOfCharacters);
108 DALI_LOG_ERROR(" mTextUpdateInfo.mStartGlyphIndex = %u\n", impl.mTextUpdateInfo.mStartGlyphIndex);
109 DALI_LOG_ERROR(" mTextUpdateInfo.mStartLineIndex = %u\n", impl.mTextUpdateInfo.mStartLineIndex);
110 DALI_LOG_ERROR(" mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", impl.mTextUpdateInfo.mEstimatedNumberOfLines);
111 DALI_LOG_ERROR(" mTextUpdateInfo.mClearAll = %d\n", impl.mTextUpdateInfo.mClearAll);
112 DALI_LOG_ERROR(" mTextUpdateInfo.mFullRelayoutNeeded = %d\n", impl.mTextUpdateInfo.mFullRelayoutNeeded);
113 DALI_LOG_ERROR(" mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", impl.mTextUpdateInfo.mIsLastCharacterNewParagraph);
118 startIndex = impl.mTextUpdateInfo.mParagraphCharacterIndex;
120 if(impl.mTextUpdateInfo.mClearAll ||
121 (0u != paragraphCharacters))
123 impl.ClearModelData(startIndex, startIndex + ((paragraphCharacters > 0u) ? paragraphCharacters - 1u : 0u), operations);
126 impl.mTextUpdateInfo.mClearAll = false;
128 // Whether the model is updated.
129 bool updated = false;
131 Vector<LineBreakInfo>& lineBreakInfo = impl.mModel->mLogicalModel->mLineBreakInfo;
132 const Length requestedNumberOfCharacters = impl.mTextUpdateInfo.mRequestedNumberOfCharacters;
134 if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
136 // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
137 // calculate the bidirectional info for each 'paragraph'.
138 // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
139 // is not shaped together).
140 lineBreakInfo.Resize(numberOfCharacters, TextAbstraction::LINE_NO_BREAK);
142 SetLineBreakInfo(utf32Characters,
144 requestedNumberOfCharacters,
147 if(impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
148 impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED))
150 CharacterIndex end = startIndex + requestedNumberOfCharacters;
151 LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
153 for(CharacterIndex index = startIndex; index < end; index++)
155 CharacterIndex wordEnd = index;
156 while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK))
161 if((wordEnd + 1) == end) // add last char
166 Vector<bool> hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr);
168 for(CharacterIndex i = 0; i < (wordEnd - index); i++)
172 *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK;
180 // Create the paragraph info.
181 impl.mModel->mLogicalModel->CreateParagraphInfo(startIndex,
182 requestedNumberOfCharacters);
186 const bool getScripts = Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations);
187 const bool validateFonts = Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations);
189 Vector<ScriptRun>& scripts = impl.mModel->mLogicalModel->mScriptRuns;
190 Vector<FontRun>& validFonts = impl.mModel->mLogicalModel->mFontRuns;
192 if(getScripts || validateFonts)
194 // Validates the fonts assigned by the application or assigns default ones.
195 // It makes sure all the characters are going to be rendered by the correct font.
196 MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
200 // Retrieves the scripts used in the text.
201 multilanguageSupport.SetScripts(utf32Characters,
203 requestedNumberOfCharacters,
209 // Validate the fonts set through the mark-up string.
210 Vector<FontDescriptionRun>& fontDescriptionRuns = impl.mModel->mLogicalModel->mFontDescriptionRuns;
212 // Get the default font's description.
213 TextAbstraction::FontDescription defaultFontDescription;
214 TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * impl.GetFontSizeScale();
216 //Get the number of points per one unit of point-size
217 uint32_t numberOfPointsPerOneUnitOfPointSize = impl.mFontClient.GetNumberOfPointsPerOneUnitOfPointSize();
219 if(impl.IsShowingPlaceholderText() && impl.mEventData && (nullptr != impl.mEventData->mPlaceholderFont))
221 // If the placeholder font is set specifically, only placeholder font is changed.
222 defaultFontDescription = impl.mEventData->mPlaceholderFont->mFontDescription;
223 if(impl.mEventData->mPlaceholderFont->sizeDefined)
225 defaultPointSize = impl.mEventData->mPlaceholderFont->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
228 else if(nullptr != impl.mFontDefaults)
230 // Set the normal font and the placeholder font.
231 defaultFontDescription = impl.mFontDefaults->mFontDescription;
233 if(impl.mTextFitEnabled)
235 defaultPointSize = impl.mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize;
239 defaultPointSize = impl.mFontDefaults->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
243 // Validates the fonts. If there is a character with no assigned font it sets a default one.
244 // After this call, fonts are validated.
245 multilanguageSupport.ValidateFonts(utf32Characters,
248 defaultFontDescription,
251 requestedNumberOfCharacters,
257 Vector<Character> mirroredUtf32Characters;
258 bool textMirrored = false;
259 const Length numberOfParagraphs = impl.mModel->mLogicalModel->mParagraphInfo.Count();
260 if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
262 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = impl.mModel->mLogicalModel->mBidirectionalParagraphInfo;
263 bidirectionalInfo.Reserve(numberOfParagraphs);
265 // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
266 SetBidirectionalInfo(utf32Characters,
270 requestedNumberOfCharacters,
272 (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS),
273 impl.mLayoutDirection);
275 if(0u != bidirectionalInfo.Count())
277 // Only set the character directions if there is right to left characters.
278 Vector<CharacterDirection>& directions = impl.mModel->mLogicalModel->mCharacterDirections;
279 GetCharactersDirection(bidirectionalInfo,
282 requestedNumberOfCharacters,
285 // This paragraph has right to left text. Some characters may need to be mirrored.
286 // TODO: consider if the mirrored string can be stored as well.
288 textMirrored = GetMirroredText(utf32Characters,
292 requestedNumberOfCharacters,
293 mirroredUtf32Characters);
297 // There is no right to left characters. Clear the directions vector.
298 impl.mModel->mLogicalModel->mCharacterDirections.Clear();
303 Vector<GlyphInfo>& glyphs = impl.mModel->mVisualModel->mGlyphs;
304 Vector<CharacterIndex>& glyphsToCharactersMap = impl.mModel->mVisualModel->mGlyphsToCharacters;
305 Vector<Length>& charactersPerGlyph = impl.mModel->mVisualModel->mCharactersPerGlyph;
306 Vector<GlyphIndex> newParagraphGlyphs;
307 newParagraphGlyphs.Reserve(numberOfParagraphs);
309 const Length currentNumberOfGlyphs = glyphs.Count();
310 if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
312 const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
314 ShapeText(textToShape,
319 impl.mTextUpdateInfo.mStartGlyphIndex,
320 requestedNumberOfCharacters,
322 glyphsToCharactersMap,
326 // Create the 'number of glyphs' per character and the glyph to character conversion tables.
327 impl.mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
328 impl.mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
333 const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs;
335 if(Controller::NO_OPERATION != (Controller::GET_GLYPH_METRICS & operations))
337 GlyphInfo* glyphsBuffer = glyphs.Begin();
338 impl.mMetrics->GetGlyphMetrics(glyphsBuffer + impl.mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs);
340 // Update the width and advance of all new paragraph characters.
341 for(Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it)
343 const GlyphIndex index = *it;
344 GlyphInfo& glyph = *(glyphsBuffer + index);
346 glyph.xBearing = 0.f;
353 if((nullptr != impl.mEventData) &&
354 impl.mEventData->mPreEditFlag &&
355 (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count()))
357 Dali::InputMethodContext::PreEditAttributeDataContainer attrs;
358 impl.mEventData->mInputMethodContext.GetPreeditStyle(attrs);
359 Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE;
361 // Check the type of preedit and run it.
362 for(Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++)
364 Dali::InputMethodContext::PreeditAttributeData attrData = *it;
365 DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex);
366 type = attrData.preeditType;
368 // Check the number of commit characters for the start position.
369 unsigned int numberOfCommit = impl.mEventData->mPrimaryCursorPosition - impl.mEventData->mPreEditLength;
370 Length numberOfIndices = attrData.endIndex - attrData.startIndex;
374 case Dali::InputMethodContext::PreeditStyle::UNDERLINE:
376 // Add the underline for the pre-edit text.
377 GlyphRun underlineRun;
378 underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
379 underlineRun.numberOfGlyphs = numberOfIndices;
380 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
382 //Mark-up processor case
383 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
385 impl.CopyUnderlinedFromLogicalToVisualModels(false);
389 case Dali::InputMethodContext::PreeditStyle::REVERSE:
391 Vector4 textColor = impl.mModel->mVisualModel->GetTextColor();
392 ColorRun backgroundColorRun;
393 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
394 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
395 backgroundColorRun.color = textColor;
396 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
398 Vector4 backgroundColor = impl.mModel->mVisualModel->GetBackgroundColor();
399 if(backgroundColor.a == 0) // There is no text background color.
401 // Try use the control's background color.
402 if(nullptr != impl.mEditableControlInterface)
404 impl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
405 if(backgroundColor.a == 0) // There is no control background color.
407 // Determines black or white color according to text color.
408 // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
409 float L = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b;
410 backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE;
415 Vector<ColorRun> colorRuns;
416 colorRuns.Resize(1u);
417 ColorRun& colorRun = *(colorRuns.Begin());
418 colorRun.color = backgroundColor;
419 colorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
420 colorRun.characterRun.numberOfCharacters = numberOfIndices;
421 impl.mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
423 //Mark-up processor case
424 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
426 impl.CopyUnderlinedFromLogicalToVisualModels(false);
430 case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
432 ColorRun backgroundColorRun;
433 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
434 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
435 backgroundColorRun.color = LIGHT_BLUE;
436 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
438 //Mark-up processor case
439 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
441 impl.CopyUnderlinedFromLogicalToVisualModels(false);
445 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
447 // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together.
448 ColorRun backgroundColorRun;
449 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
450 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
451 backgroundColorRun.color = BACKGROUND_SUB4;
452 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
454 GlyphRun underlineRun;
455 underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
456 underlineRun.numberOfGlyphs = numberOfIndices;
457 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
459 //Mark-up processor case
460 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
462 impl.CopyUnderlinedFromLogicalToVisualModels(false);
466 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2:
468 // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together.
469 ColorRun backgroundColorRun;
470 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
471 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
472 backgroundColorRun.color = BACKGROUND_SUB5;
473 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
475 GlyphRun underlineRun;
476 underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
477 underlineRun.numberOfGlyphs = numberOfIndices;
478 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
480 //Mark-up processor case
481 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
483 impl.CopyUnderlinedFromLogicalToVisualModels(false);
487 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3:
489 // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together.
490 ColorRun backgroundColorRun;
491 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
492 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
493 backgroundColorRun.color = BACKGROUND_SUB6;
494 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
496 GlyphRun underlineRun;
497 underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
498 underlineRun.numberOfGlyphs = numberOfIndices;
499 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
501 //Mark-up processor case
502 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
504 impl.CopyUnderlinedFromLogicalToVisualModels(false);
508 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4:
510 // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together.
511 ColorRun backgroundColorRun;
512 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
513 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
514 backgroundColorRun.color = BACKGROUND_SUB7;
515 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
517 GlyphRun underlineRun;
518 underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
519 underlineRun.numberOfGlyphs = numberOfIndices;
520 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
522 //Mark-up processor case
523 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
525 impl.CopyUnderlinedFromLogicalToVisualModels(false);
529 case Dali::InputMethodContext::PreeditStyle::NONE:
540 if(Controller::NO_OPERATION != (Controller::COLOR & operations))
542 // Set the color runs in glyphs.
543 SetColorSegmentationInfo(impl.mModel->mLogicalModel->mColorRuns,
544 impl.mModel->mVisualModel->mCharactersToGlyph,
545 impl.mModel->mVisualModel->mGlyphsPerCharacter,
547 impl.mTextUpdateInfo.mStartGlyphIndex,
548 requestedNumberOfCharacters,
549 impl.mModel->mVisualModel->mColors,
550 impl.mModel->mVisualModel->mColorIndices);
552 // Set the background color runs in glyphs.
553 SetColorSegmentationInfo(impl.mModel->mLogicalModel->mBackgroundColorRuns,
554 impl.mModel->mVisualModel->mCharactersToGlyph,
555 impl.mModel->mVisualModel->mGlyphsPerCharacter,
557 impl.mTextUpdateInfo.mStartGlyphIndex,
558 requestedNumberOfCharacters,
559 impl.mModel->mVisualModel->mBackgroundColors,
560 impl.mModel->mVisualModel->mBackgroundColorIndices);
565 if((Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) &&
566 !((nullptr != impl.mEventData) &&
567 impl.mEventData->mPreEditFlag &&
568 (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count())))
570 //Mark-up processor case
571 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
573 impl.CopyUnderlinedFromLogicalToVisualModels(true);
579 // The estimated number of lines. Used to avoid reallocations when layouting.
580 impl.mTextUpdateInfo.mEstimatedNumberOfLines = std::max(impl.mModel->mVisualModel->mLines.Count(), impl.mModel->mLogicalModel->mParagraphInfo.Count());
582 // Set the previous number of characters for the next time the text is updated.
583 impl.mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters;
588 } // namespace Dali::Toolkit::Text