2 * Copyright (c) 2021 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
39 #if defined(DEBUG_ENABLED)
40 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
43 // The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B)
44 // based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
45 constexpr float BRIGHTNESS_THRESHOLD = 0.179f;
46 constexpr float CONSTANT_R = 0.2126f;
47 constexpr float CONSTANT_G = 0.7152f;
48 constexpr float CONSTANT_B = 0.0722f;
49 constexpr Dali::Vector4 BLACK(0.f, 0.f, 0.f, 1.f);
50 constexpr Dali::Vector4 WHITE(1.f, 1.f, 1.f, 1.f);
51 constexpr Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f);
52 constexpr Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f);
53 constexpr Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f);
54 constexpr Dali::Vector4 BACKGROUND_SUB6(1.f, 0.5f, 0.5f, 1.f);
55 constexpr Dali::Vector4 BACKGROUND_SUB7(1.f, 0.8f, 0.8f, 1.f);
58 bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask operationsRequired)
60 DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel\n");
62 // Calculate the operations to be done.
63 const OperationsMask operations = static_cast<OperationsMask>(impl.mOperationsPending & operationsRequired);
65 if(Controller::NO_OPERATION == operations)
67 // Nothing to do if no operations are pending and required.
71 Vector<Character>& srcCharacters = impl.mModel->mLogicalModel->mText;
72 Vector<Character> displayCharacters;
73 bool useHiddenText = false;
74 if(impl.mHiddenInput && impl.mEventData != nullptr && !impl.mEventData->mIsShowingPlaceholderText)
76 impl.mHiddenInput->Substitute(srcCharacters, displayCharacters);
80 Vector<Character>& utf32Characters = useHiddenText ? displayCharacters : srcCharacters;
81 const Length numberOfCharacters = utf32Characters.Count();
83 // Index to the first character of the first paragraph to be updated.
84 CharacterIndex startIndex = 0u;
85 // Number of characters of the paragraphs to be removed.
86 Length paragraphCharacters = 0u;
88 impl.CalculateTextUpdateIndices(paragraphCharacters);
90 // Check whether the indices for updating the text is valid
91 if(numberOfCharacters > 0u &&
92 (impl.mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters ||
93 impl.mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters))
95 std::string currentText;
96 Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText);
98 DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n");
99 DALI_LOG_ERROR("Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str());
101 // Dump mTextUpdateInfo
102 DALI_LOG_ERROR("Dump mTextUpdateInfo:\n");
103 DALI_LOG_ERROR(" mTextUpdateInfo.mCharacterIndex = %u\n", impl.mTextUpdateInfo.mCharacterIndex);
104 DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToRemove);
105 DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToAdd);
106 DALI_LOG_ERROR(" mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mPreviousNumberOfCharacters);
107 DALI_LOG_ERROR(" mTextUpdateInfo.mParagraphCharacterIndex = %u\n", impl.mTextUpdateInfo.mParagraphCharacterIndex);
108 DALI_LOG_ERROR(" mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mRequestedNumberOfCharacters);
109 DALI_LOG_ERROR(" mTextUpdateInfo.mStartGlyphIndex = %u\n", impl.mTextUpdateInfo.mStartGlyphIndex);
110 DALI_LOG_ERROR(" mTextUpdateInfo.mStartLineIndex = %u\n", impl.mTextUpdateInfo.mStartLineIndex);
111 DALI_LOG_ERROR(" mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", impl.mTextUpdateInfo.mEstimatedNumberOfLines);
112 DALI_LOG_ERROR(" mTextUpdateInfo.mClearAll = %d\n", impl.mTextUpdateInfo.mClearAll);
113 DALI_LOG_ERROR(" mTextUpdateInfo.mFullRelayoutNeeded = %d\n", impl.mTextUpdateInfo.mFullRelayoutNeeded);
114 DALI_LOG_ERROR(" mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", impl.mTextUpdateInfo.mIsLastCharacterNewParagraph);
119 startIndex = impl.mTextUpdateInfo.mParagraphCharacterIndex;
121 if(impl.mTextUpdateInfo.mClearAll ||
122 (0u != paragraphCharacters))
124 impl.ClearModelData(startIndex, startIndex + ((paragraphCharacters > 0u) ? paragraphCharacters - 1u : 0u), operations);
127 impl.mTextUpdateInfo.mClearAll = false;
129 // Whether the model is updated.
130 bool updated = false;
132 Vector<LineBreakInfo>& lineBreakInfo = impl.mModel->mLogicalModel->mLineBreakInfo;
133 const Length requestedNumberOfCharacters = impl.mTextUpdateInfo.mRequestedNumberOfCharacters;
135 if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
137 // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
138 // calculate the bidirectional info for each 'paragraph'.
139 // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
140 // is not shaped together).
141 lineBreakInfo.Resize(numberOfCharacters, TextAbstraction::LINE_NO_BREAK);
143 SetLineBreakInfo(utf32Characters,
145 requestedNumberOfCharacters,
148 if(impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
149 impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED))
151 CharacterIndex end = startIndex + requestedNumberOfCharacters;
152 LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
154 for(CharacterIndex index = startIndex; index < end; index++)
156 CharacterIndex wordEnd = index;
157 while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK))
162 if((wordEnd + 1) == end) // add last char
167 Vector<bool> hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr);
169 for(CharacterIndex i = 0; i < (wordEnd - index); i++)
173 *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK;
181 // Create the paragraph info.
182 impl.mModel->mLogicalModel->CreateParagraphInfo(startIndex,
183 requestedNumberOfCharacters);
187 const bool getScripts = Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations);
188 const bool validateFonts = Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations);
190 Vector<ScriptRun>& scripts = impl.mModel->mLogicalModel->mScriptRuns;
191 Vector<FontRun>& validFonts = impl.mModel->mLogicalModel->mFontRuns;
193 if(getScripts || validateFonts)
195 // Validates the fonts assigned by the application or assigns default ones.
196 // It makes sure all the characters are going to be rendered by the correct font.
197 MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
201 // Retrieves the scripts used in the text.
202 multilanguageSupport.SetScripts(utf32Characters,
204 requestedNumberOfCharacters,
210 // Validate the fonts set through the mark-up string.
211 Vector<FontDescriptionRun>& fontDescriptionRuns = impl.mModel->mLogicalModel->mFontDescriptionRuns;
213 // Get the default font's description.
214 TextAbstraction::FontDescription defaultFontDescription;
215 TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * impl.mFontSizeScale;
217 //Get the number of points per one unit of point-size
218 uint32_t numberOfPointsPerOneUnitOfPointSize = impl.mFontClient.GetNumberOfPointsPerOneUnitOfPointSize();
220 if(impl.IsShowingPlaceholderText() && impl.mEventData && (nullptr != impl.mEventData->mPlaceholderFont))
222 // If the placeholder font is set specifically, only placeholder font is changed.
223 defaultFontDescription = impl.mEventData->mPlaceholderFont->mFontDescription;
224 if(impl.mEventData->mPlaceholderFont->sizeDefined)
226 defaultPointSize = impl.mEventData->mPlaceholderFont->mDefaultPointSize * impl.mFontSizeScale * numberOfPointsPerOneUnitOfPointSize;
229 else if(nullptr != impl.mFontDefaults)
231 // Set the normal font and the placeholder font.
232 defaultFontDescription = impl.mFontDefaults->mFontDescription;
234 if(impl.mTextFitEnabled)
236 defaultPointSize = impl.mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize;
240 defaultPointSize = impl.mFontDefaults->mDefaultPointSize * impl.mFontSizeScale * numberOfPointsPerOneUnitOfPointSize;
244 // Validates the fonts. If there is a character with no assigned font it sets a default one.
245 // After this call, fonts are validated.
246 multilanguageSupport.ValidateFonts(utf32Characters,
249 defaultFontDescription,
252 requestedNumberOfCharacters,
258 Vector<Character> mirroredUtf32Characters;
259 bool textMirrored = false;
260 const Length numberOfParagraphs = impl.mModel->mLogicalModel->mParagraphInfo.Count();
261 if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
263 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = impl.mModel->mLogicalModel->mBidirectionalParagraphInfo;
264 bidirectionalInfo.Reserve(numberOfParagraphs);
266 // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
267 SetBidirectionalInfo(utf32Characters,
271 requestedNumberOfCharacters,
273 (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS),
274 impl.mLayoutDirection);
276 if(0u != bidirectionalInfo.Count())
278 // Only set the character directions if there is right to left characters.
279 Vector<CharacterDirection>& directions = impl.mModel->mLogicalModel->mCharacterDirections;
280 GetCharactersDirection(bidirectionalInfo,
283 requestedNumberOfCharacters,
286 // This paragraph has right to left text. Some characters may need to be mirrored.
287 // TODO: consider if the mirrored string can be stored as well.
289 textMirrored = GetMirroredText(utf32Characters,
293 requestedNumberOfCharacters,
294 mirroredUtf32Characters);
298 // There is no right to left characters. Clear the directions vector.
299 impl.mModel->mLogicalModel->mCharacterDirections.Clear();
304 Vector<GlyphInfo>& glyphs = impl.mModel->mVisualModel->mGlyphs;
305 Vector<CharacterIndex>& glyphsToCharactersMap = impl.mModel->mVisualModel->mGlyphsToCharacters;
306 Vector<Length>& charactersPerGlyph = impl.mModel->mVisualModel->mCharactersPerGlyph;
307 Vector<GlyphIndex> newParagraphGlyphs;
308 newParagraphGlyphs.Reserve(numberOfParagraphs);
310 const Length currentNumberOfGlyphs = glyphs.Count();
311 if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
313 const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
315 ShapeText(textToShape,
320 impl.mTextUpdateInfo.mStartGlyphIndex,
321 requestedNumberOfCharacters,
323 glyphsToCharactersMap,
327 // Create the 'number of glyphs' per character and the glyph to character conversion tables.
328 impl.mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
329 impl.mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
334 const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs;
336 if(Controller::NO_OPERATION != (Controller::GET_GLYPH_METRICS & operations))
338 GlyphInfo* glyphsBuffer = glyphs.Begin();
339 impl.mMetrics->GetGlyphMetrics(glyphsBuffer + impl.mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs);
341 // Update the width and advance of all new paragraph characters.
342 for(Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it)
344 const GlyphIndex index = *it;
345 GlyphInfo& glyph = *(glyphsBuffer + index);
347 glyph.xBearing = 0.f;
354 if((nullptr != impl.mEventData) &&
355 impl.mEventData->mPreEditFlag &&
356 (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count()))
358 Dali::InputMethodContext::PreEditAttributeDataContainer attrs;
359 impl.mEventData->mInputMethodContext.GetPreeditStyle(attrs);
360 Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE;
362 // Check the type of preedit and run it.
363 for(Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++)
365 Dali::InputMethodContext::PreeditAttributeData attrData = *it;
366 DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex);
367 type = attrData.preeditType;
369 // Check the number of commit characters for the start position.
370 unsigned int numberOfCommit = impl.mEventData->mPrimaryCursorPosition - impl.mEventData->mPreEditLength;
371 Length numberOfIndices = attrData.endIndex - attrData.startIndex;
375 case Dali::InputMethodContext::PreeditStyle::UNDERLINE:
377 // Add the underline for the pre-edit text.
378 GlyphRun underlineRun;
379 underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
380 underlineRun.numberOfGlyphs = numberOfIndices;
381 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
383 //Mark-up processor case
384 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
386 impl.CopyUnderlinedFromLogicalToVisualModels(false);
390 case Dali::InputMethodContext::PreeditStyle::REVERSE:
392 Vector4 textColor = impl.mModel->mVisualModel->GetTextColor();
393 ColorRun backgroundColorRun;
394 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
395 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
396 backgroundColorRun.color = textColor;
397 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
399 Vector4 backgroundColor = impl.mModel->mVisualModel->GetBackgroundColor();
400 if(backgroundColor.a == 0) // There is no text background color.
402 // Try use the control's background color.
403 if(nullptr != impl.mEditableControlInterface)
405 impl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
406 if(backgroundColor.a == 0) // There is no control background color.
408 // Determines black or white color according to text color.
409 // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
410 float L = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b;
411 backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE;
416 Vector<ColorRun> colorRuns;
417 colorRuns.Resize(1u);
418 ColorRun& colorRun = *(colorRuns.Begin());
419 colorRun.color = backgroundColor;
420 colorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
421 colorRun.characterRun.numberOfCharacters = numberOfIndices;
422 impl.mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
424 //Mark-up processor case
425 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
427 impl.CopyUnderlinedFromLogicalToVisualModels(false);
431 case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
433 ColorRun backgroundColorRun;
434 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
435 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
436 backgroundColorRun.color = LIGHT_BLUE;
437 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
439 //Mark-up processor case
440 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
442 impl.CopyUnderlinedFromLogicalToVisualModels(false);
446 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
448 // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together.
449 ColorRun backgroundColorRun;
450 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
451 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
452 backgroundColorRun.color = BACKGROUND_SUB4;
453 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
455 GlyphRun underlineRun;
456 underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
457 underlineRun.numberOfGlyphs = numberOfIndices;
458 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
460 //Mark-up processor case
461 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
463 impl.CopyUnderlinedFromLogicalToVisualModels(false);
467 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2:
469 // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together.
470 ColorRun backgroundColorRun;
471 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
472 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
473 backgroundColorRun.color = BACKGROUND_SUB5;
474 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
476 GlyphRun underlineRun;
477 underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
478 underlineRun.numberOfGlyphs = numberOfIndices;
479 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
481 //Mark-up processor case
482 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
484 impl.CopyUnderlinedFromLogicalToVisualModels(false);
488 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3:
490 // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together.
491 ColorRun backgroundColorRun;
492 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
493 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
494 backgroundColorRun.color = BACKGROUND_SUB6;
495 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
497 GlyphRun underlineRun;
498 underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
499 underlineRun.numberOfGlyphs = numberOfIndices;
500 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
502 //Mark-up processor case
503 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
505 impl.CopyUnderlinedFromLogicalToVisualModels(false);
509 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4:
511 // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together.
512 ColorRun backgroundColorRun;
513 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
514 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
515 backgroundColorRun.color = BACKGROUND_SUB7;
516 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
518 GlyphRun underlineRun;
519 underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
520 underlineRun.numberOfGlyphs = numberOfIndices;
521 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
523 //Mark-up processor case
524 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
526 impl.CopyUnderlinedFromLogicalToVisualModels(false);
530 case Dali::InputMethodContext::PreeditStyle::NONE:
541 if(Controller::NO_OPERATION != (Controller::COLOR & operations))
543 // Set the color runs in glyphs.
544 SetColorSegmentationInfo(impl.mModel->mLogicalModel->mColorRuns,
545 impl.mModel->mVisualModel->mCharactersToGlyph,
546 impl.mModel->mVisualModel->mGlyphsPerCharacter,
548 impl.mTextUpdateInfo.mStartGlyphIndex,
549 requestedNumberOfCharacters,
550 impl.mModel->mVisualModel->mColors,
551 impl.mModel->mVisualModel->mColorIndices);
553 // Set the background color runs in glyphs.
554 SetColorSegmentationInfo(impl.mModel->mLogicalModel->mBackgroundColorRuns,
555 impl.mModel->mVisualModel->mCharactersToGlyph,
556 impl.mModel->mVisualModel->mGlyphsPerCharacter,
558 impl.mTextUpdateInfo.mStartGlyphIndex,
559 requestedNumberOfCharacters,
560 impl.mModel->mVisualModel->mBackgroundColors,
561 impl.mModel->mVisualModel->mBackgroundColorIndices);
566 if((Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) &&
567 !((nullptr != impl.mEventData) &&
568 impl.mEventData->mPreEditFlag &&
569 (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count())))
571 //Mark-up processor case
572 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
574 impl.CopyUnderlinedFromLogicalToVisualModels(true);
580 // The estimated number of lines. Used to avoid reallocations when layouting.
581 impl.mTextUpdateInfo.mEstimatedNumberOfLines = std::max(impl.mModel->mVisualModel->mLines.Count(), impl.mModel->mLogicalModel->mParagraphInfo.Count());
583 // Set the previous number of characters for the next time the text is updated.
584 impl.mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters;
589 } // namespace Dali::Toolkit::Text