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/controller/text-controller-impl-model-updater.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/trace.h>
24 #include <dali/public-api/math/math-utils.h>
27 #include <dali-toolkit/internal/text/bidirectional-support.h>
28 #include <dali-toolkit/internal/text/character-set-conversion.h>
29 #include <dali-toolkit/internal/text/color-segmentation.h>
30 #include <dali-toolkit/internal/text/hyphenator.h>
31 #include <dali-toolkit/internal/text/multi-language-support.h>
32 #include <dali-toolkit/internal/text/segmentation.h>
33 #include <dali-toolkit/internal/text/shaper.h>
34 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
36 namespace Dali::Toolkit::Text
40 #if defined(DEBUG_ENABLED)
41 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
44 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
46 // The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B)
47 // based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
48 constexpr float BRIGHTNESS_THRESHOLD = 0.179f;
49 constexpr float CONSTANT_R = 0.2126f;
50 constexpr float CONSTANT_G = 0.7152f;
51 constexpr float CONSTANT_B = 0.0722f;
52 constexpr Dali::Vector4 BLACK(0.f, 0.f, 0.f, 1.f);
53 constexpr Dali::Vector4 WHITE(1.f, 1.f, 1.f, 1.f);
54 constexpr Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f);
55 constexpr Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f);
56 constexpr Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f);
57 constexpr Dali::Vector4 BACKGROUND_SUB6(1.f, 0.5f, 0.5f, 1.f);
58 constexpr Dali::Vector4 BACKGROUND_SUB7(1.f, 0.8f, 0.8f, 1.f);
61 bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask operationsRequired)
63 DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel\n");
65 // Calculate the operations to be done.
66 const OperationsMask operations = static_cast<OperationsMask>(impl.mOperationsPending & operationsRequired);
68 if(Controller::NO_OPERATION == operations)
70 // Nothing to do if no operations are pending and required.
73 DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_MODEL_UPDATE");
75 Vector<Character>& srcCharacters = impl.mModel->mLogicalModel->mText;
76 Vector<Character> displayCharacters;
77 bool useHiddenText = false;
78 if(impl.mHiddenInput && impl.mEventData != nullptr)
80 if(impl.mEventData->mIsShowingPlaceholderText)
82 impl.mHiddenInput->InitPreviousTextCount();
86 impl.mHiddenInput->Substitute(srcCharacters, displayCharacters, impl.mEventData->mPrimaryCursorPosition);
91 Vector<Character>& utf32Characters = useHiddenText ? displayCharacters : srcCharacters;
92 const Length numberOfCharacters = utf32Characters.Count();
94 // Index to the first character of the first paragraph to be updated.
95 CharacterIndex startIndex = 0u;
96 // Number of characters of the paragraphs to be removed.
97 Length paragraphCharacters = 0u;
99 impl.CalculateTextUpdateIndices(paragraphCharacters);
101 // Check whether the indices for updating the text is valid
102 if(numberOfCharacters > 0u &&
103 (impl.mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters ||
104 impl.mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters))
106 std::string currentText;
107 Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText);
109 DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n");
110 DALI_LOG_ERROR("Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str());
112 // Dump mTextUpdateInfo
113 DALI_LOG_ERROR("Dump mTextUpdateInfo:\n");
114 DALI_LOG_ERROR(" mTextUpdateInfo.mCharacterIndex = %u\n", impl.mTextUpdateInfo.mCharacterIndex);
115 DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToRemove);
116 DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToAdd);
117 DALI_LOG_ERROR(" mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mPreviousNumberOfCharacters);
118 DALI_LOG_ERROR(" mTextUpdateInfo.mParagraphCharacterIndex = %u\n", impl.mTextUpdateInfo.mParagraphCharacterIndex);
119 DALI_LOG_ERROR(" mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mRequestedNumberOfCharacters);
120 DALI_LOG_ERROR(" mTextUpdateInfo.mStartGlyphIndex = %u\n", impl.mTextUpdateInfo.mStartGlyphIndex);
121 DALI_LOG_ERROR(" mTextUpdateInfo.mStartLineIndex = %u\n", impl.mTextUpdateInfo.mStartLineIndex);
122 DALI_LOG_ERROR(" mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", impl.mTextUpdateInfo.mEstimatedNumberOfLines);
123 DALI_LOG_ERROR(" mTextUpdateInfo.mClearAll = %d\n", impl.mTextUpdateInfo.mClearAll);
124 DALI_LOG_ERROR(" mTextUpdateInfo.mFullRelayoutNeeded = %d\n", impl.mTextUpdateInfo.mFullRelayoutNeeded);
125 DALI_LOG_ERROR(" mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", impl.mTextUpdateInfo.mIsLastCharacterNewParagraph);
130 startIndex = impl.mTextUpdateInfo.mParagraphCharacterIndex;
132 if(impl.mTextUpdateInfo.mClearAll ||
133 (0u != paragraphCharacters))
135 impl.ClearModelData(startIndex, startIndex + ((paragraphCharacters > 0u) ? paragraphCharacters - 1u : 0u), operations);
138 impl.mTextUpdateInfo.mClearAll = false;
140 // Whether the model is updated.
141 bool updated = false;
143 Vector<LineBreakInfo>& lineBreakInfo = impl.mModel->mLogicalModel->mLineBreakInfo;
144 const Length requestedNumberOfCharacters = impl.mTextUpdateInfo.mRequestedNumberOfCharacters;
146 if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
148 // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
149 // calculate the bidirectional info for each 'paragraph'.
150 // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
151 // is not shaped together).
152 lineBreakInfo.Resize(numberOfCharacters, TextAbstraction::LINE_NO_BREAK);
154 SetLineBreakInfo(utf32Characters,
156 requestedNumberOfCharacters,
159 if(impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
160 impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED))
162 CharacterIndex end = startIndex + requestedNumberOfCharacters;
163 LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
165 for(CharacterIndex index = startIndex; index < end; index++)
167 CharacterIndex wordEnd = index;
168 while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK))
173 if((wordEnd + 1) == end) // add last char
178 Vector<bool> hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr);
180 for(CharacterIndex i = 0; i < (wordEnd - index); i++)
184 *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK;
192 // Create the paragraph info.
193 impl.mModel->mLogicalModel->CreateParagraphInfo(startIndex,
194 requestedNumberOfCharacters);
198 const bool getScripts = Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations);
199 const bool validateFonts = Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations);
201 Vector<ScriptRun>& scripts = impl.mModel->mLogicalModel->mScriptRuns;
202 Vector<FontRun>& validFonts = impl.mModel->mLogicalModel->mFontRuns;
204 if(getScripts || validateFonts)
206 // Validates the fonts assigned by the application or assigns default ones.
207 // It makes sure all the characters are going to be rendered by the correct font.
208 MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
212 // Retrieves the scripts used in the text.
213 multilanguageSupport.SetScripts(utf32Characters,
215 requestedNumberOfCharacters,
221 // Validate the fonts set through the mark-up string.
222 Vector<FontDescriptionRun>& fontDescriptionRuns = impl.mModel->mLogicalModel->mFontDescriptionRuns;
224 // Get the default font's description.
225 TextAbstraction::FontDescription defaultFontDescription;
226 TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * impl.GetFontSizeScale();
228 //Get the number of points per one unit of point-size
229 uint32_t numberOfPointsPerOneUnitOfPointSize = impl.mFontClient.GetNumberOfPointsPerOneUnitOfPointSize();
231 if(impl.IsShowingPlaceholderText() && impl.mEventData && (nullptr != impl.mEventData->mPlaceholderFont))
233 // If the placeholder font is set specifically, only placeholder font is changed.
234 defaultFontDescription = impl.mEventData->mPlaceholderFont->mFontDescription;
235 if(impl.mEventData->mPlaceholderFont->sizeDefined)
237 defaultPointSize = impl.mEventData->mPlaceholderFont->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
240 else if(nullptr != impl.mFontDefaults)
242 // Set the normal font and the placeholder font.
243 defaultFontDescription = impl.mFontDefaults->mFontDescription;
245 if(impl.mTextFitEnabled)
247 defaultPointSize = impl.mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize;
251 defaultPointSize = impl.mFontDefaults->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
255 // Validates the fonts. If there is a character with no assigned font it sets a default one.
256 // After this call, fonts are validated.
257 multilanguageSupport.ValidateFonts(utf32Characters,
260 defaultFontDescription,
263 requestedNumberOfCharacters,
269 Vector<Character> mirroredUtf32Characters;
270 bool textMirrored = false;
271 const Length numberOfParagraphs = impl.mModel->mLogicalModel->mParagraphInfo.Count();
272 if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
274 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = impl.mModel->mLogicalModel->mBidirectionalParagraphInfo;
275 bidirectionalInfo.Reserve(numberOfParagraphs);
277 // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
278 SetBidirectionalInfo(utf32Characters,
282 requestedNumberOfCharacters,
284 (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS),
285 impl.mLayoutDirection);
287 if(0u != bidirectionalInfo.Count())
289 // Only set the character directions if there is right to left characters.
290 Vector<CharacterDirection>& directions = impl.mModel->mLogicalModel->mCharacterDirections;
291 GetCharactersDirection(bidirectionalInfo,
294 requestedNumberOfCharacters,
297 // This paragraph has right to left text. Some characters may need to be mirrored.
298 // TODO: consider if the mirrored string can be stored as well.
300 textMirrored = GetMirroredText(utf32Characters,
304 requestedNumberOfCharacters,
305 mirroredUtf32Characters);
309 // There is no right to left characters. Clear the directions vector.
310 impl.mModel->mLogicalModel->mCharacterDirections.Clear();
315 Vector<GlyphInfo>& glyphs = impl.mModel->mVisualModel->mGlyphs;
316 Vector<CharacterIndex>& glyphsToCharactersMap = impl.mModel->mVisualModel->mGlyphsToCharacters;
317 Vector<Length>& charactersPerGlyph = impl.mModel->mVisualModel->mCharactersPerGlyph;
318 Vector<GlyphIndex> newParagraphGlyphs;
319 newParagraphGlyphs.Reserve(numberOfParagraphs);
321 const Length currentNumberOfGlyphs = glyphs.Count();
322 if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
324 const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
326 ShapeText(textToShape,
331 impl.mTextUpdateInfo.mStartGlyphIndex,
332 requestedNumberOfCharacters,
334 glyphsToCharactersMap,
338 // Create the 'number of glyphs' per character and the glyph to character conversion tables.
339 impl.mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
340 impl.mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
345 const Length numberOfGlyphs = static_cast<Length>(glyphs.Count()) - currentNumberOfGlyphs;
347 if(Controller::NO_OPERATION != (Controller::GET_GLYPH_METRICS & operations))
349 GlyphInfo* glyphsBuffer = glyphs.Begin();
350 impl.mMetrics->GetGlyphMetrics(glyphsBuffer + impl.mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs);
352 // Update the width and advance of all new paragraph characters.
353 for(Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it)
355 const GlyphIndex index = *it;
356 GlyphInfo& glyph = *(glyphsBuffer + index);
358 glyph.xBearing = 0.f;
365 if((nullptr != impl.mEventData) &&
366 impl.mEventData->mPreEditFlag &&
367 (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count()))
369 Dali::InputMethodContext::PreEditAttributeDataContainer attrs;
370 impl.mEventData->mInputMethodContext.GetPreeditStyle(attrs);
371 Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE;
373 // Check the type of preedit and run it.
374 for(Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++)
376 Dali::InputMethodContext::PreeditAttributeData attrData = *it;
377 DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex);
378 type = attrData.preeditType;
380 // Check the number of commit characters for the start position.
381 unsigned int numberOfCommit = impl.mEventData->mPrimaryCursorPosition - impl.mEventData->mPreEditLength;
382 Length numberOfIndices = attrData.endIndex - attrData.startIndex;
386 case Dali::InputMethodContext::PreeditStyle::UNDERLINE:
388 // Add the underline for the pre-edit text.
389 UnderlinedGlyphRun underlineRun;
390 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
391 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
392 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
394 //Mark-up processor case
395 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
396 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
398 impl.CopyUnderlinedFromLogicalToVisualModels(false);
402 case Dali::InputMethodContext::PreeditStyle::REVERSE:
404 Vector4 textColor = impl.mModel->mVisualModel->GetTextColor();
405 ColorRun backgroundColorRun;
406 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
407 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
408 backgroundColorRun.color = textColor;
409 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
411 Vector4 backgroundColor = impl.mModel->mVisualModel->GetBackgroundColor();
412 if(Dali::EqualsZero(backgroundColor.a)) // There is no text background color.
414 // Try use the control's background color.
415 if(nullptr != impl.mEditableControlInterface)
417 impl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
418 if(Dali::EqualsZero(backgroundColor.a)) // There is no control background color.
420 // Determines black or white color according to text color.
421 // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
422 float L = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b;
423 backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE;
428 Vector<ColorRun> colorRuns;
429 colorRuns.Resize(1u);
430 ColorRun& colorRun = *(colorRuns.Begin());
431 colorRun.color = backgroundColor;
432 colorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
433 colorRun.characterRun.numberOfCharacters = numberOfIndices;
434 impl.mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
436 //Mark-up processor case
437 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
438 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
440 impl.CopyUnderlinedFromLogicalToVisualModels(false);
444 case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
446 ColorRun backgroundColorRun;
447 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
448 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
449 backgroundColorRun.color = LIGHT_BLUE;
450 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
452 //Mark-up processor case
453 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
454 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
456 impl.CopyUnderlinedFromLogicalToVisualModels(false);
460 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
462 // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together.
463 ColorRun backgroundColorRun;
464 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
465 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
466 backgroundColorRun.color = BACKGROUND_SUB4;
467 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
469 UnderlinedGlyphRun underlineRun;
470 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
471 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
472 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
474 //Mark-up processor case
475 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
476 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
478 impl.CopyUnderlinedFromLogicalToVisualModels(false);
482 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2:
484 // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together.
485 ColorRun backgroundColorRun;
486 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
487 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
488 backgroundColorRun.color = BACKGROUND_SUB5;
489 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
491 UnderlinedGlyphRun underlineRun;
492 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
493 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
494 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
496 //Mark-up processor case
497 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
498 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
500 impl.CopyUnderlinedFromLogicalToVisualModels(false);
504 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3:
506 // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together.
507 ColorRun backgroundColorRun;
508 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
509 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
510 backgroundColorRun.color = BACKGROUND_SUB6;
511 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
513 UnderlinedGlyphRun underlineRun;
514 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
515 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
516 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
518 //Mark-up processor case
519 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
520 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
522 impl.CopyUnderlinedFromLogicalToVisualModels(false);
526 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4:
528 // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together.
529 ColorRun backgroundColorRun;
530 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
531 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
532 backgroundColorRun.color = BACKGROUND_SUB7;
533 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
535 UnderlinedGlyphRun underlineRun;
536 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
537 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
538 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
540 //Mark-up processor case
541 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
542 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
544 impl.CopyUnderlinedFromLogicalToVisualModels(false);
548 case Dali::InputMethodContext::PreeditStyle::NONE:
559 if(Controller::NO_OPERATION != (Controller::COLOR & operations))
561 // Set the color runs in glyphs.
562 SetColorSegmentationInfo(impl.mModel->mLogicalModel->mColorRuns,
563 impl.mModel->mVisualModel->mCharactersToGlyph,
564 impl.mModel->mVisualModel->mGlyphsPerCharacter,
566 impl.mTextUpdateInfo.mStartGlyphIndex,
567 requestedNumberOfCharacters,
568 impl.mModel->mVisualModel->mColors,
569 impl.mModel->mVisualModel->mColorIndices);
571 // Set the background color runs in glyphs.
572 SetColorSegmentationInfo(impl.mModel->mLogicalModel->mBackgroundColorRuns,
573 impl.mModel->mVisualModel->mCharactersToGlyph,
574 impl.mModel->mVisualModel->mGlyphsPerCharacter,
576 impl.mTextUpdateInfo.mStartGlyphIndex,
577 requestedNumberOfCharacters,
578 impl.mModel->mVisualModel->mBackgroundColors,
579 impl.mModel->mVisualModel->mBackgroundColorIndices);
584 if((Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) &&
585 !((nullptr != impl.mEventData) &&
586 impl.mEventData->mPreEditFlag &&
587 (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count())))
589 //Mark-up processor case
590 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
591 impl.mModel->mLogicalModel->mUnderlineRunsUpdated ||
592 impl.mModel->mLogicalModel->mCharacterSpacingRunsUpdated ||
593 impl.mModel->mLogicalModel->mStrikethroughRunsUpdated)
595 impl.CopyUnderlinedFromLogicalToVisualModels(true);
596 impl.CopyStrikethroughFromLogicalToVisualModels();
597 impl.CopyCharacterSpacingFromLogicalToVisualModels();
603 // The estimated number of lines. Used to avoid reallocations when layouting.
604 impl.mTextUpdateInfo.mEstimatedNumberOfLines = std::max(impl.mModel->mVisualModel->mLines.Count(), impl.mModel->mLogicalModel->mParagraphInfo.Count());
606 // Set the previous number of characters for the next time the text is updated.
607 impl.mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters;
612 } // namespace Dali::Toolkit::Text