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/public-api/math/math-utils.h>
26 #include <dali-toolkit/internal/text/bidirectional-support.h>
27 #include <dali-toolkit/internal/text/character-set-conversion.h>
28 #include <dali-toolkit/internal/text/color-segmentation.h>
29 #include <dali-toolkit/internal/text/hyphenator.h>
30 #include <dali-toolkit/internal/text/multi-language-support.h>
31 #include <dali-toolkit/internal/text/segmentation.h>
32 #include <dali-toolkit/internal/text/shaper.h>
33 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
35 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)
76 if(impl.mEventData->mIsShowingPlaceholderText)
78 impl.mHiddenInput->InitPreviousTextCount();
82 impl.mHiddenInput->Substitute(srcCharacters, displayCharacters, impl.mEventData->mPrimaryCursorPosition);
87 Vector<Character>& utf32Characters = useHiddenText ? displayCharacters : srcCharacters;
88 const Length numberOfCharacters = utf32Characters.Count();
90 // Index to the first character of the first paragraph to be updated.
91 CharacterIndex startIndex = 0u;
92 // Number of characters of the paragraphs to be removed.
93 Length paragraphCharacters = 0u;
95 impl.CalculateTextUpdateIndices(paragraphCharacters);
97 // Check whether the indices for updating the text is valid
98 if(numberOfCharacters > 0u &&
99 (impl.mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters ||
100 impl.mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters))
102 std::string currentText;
103 Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText);
105 DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n");
106 DALI_LOG_ERROR("Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str());
108 // Dump mTextUpdateInfo
109 DALI_LOG_ERROR("Dump mTextUpdateInfo:\n");
110 DALI_LOG_ERROR(" mTextUpdateInfo.mCharacterIndex = %u\n", impl.mTextUpdateInfo.mCharacterIndex);
111 DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToRemove);
112 DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToAdd);
113 DALI_LOG_ERROR(" mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mPreviousNumberOfCharacters);
114 DALI_LOG_ERROR(" mTextUpdateInfo.mParagraphCharacterIndex = %u\n", impl.mTextUpdateInfo.mParagraphCharacterIndex);
115 DALI_LOG_ERROR(" mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mRequestedNumberOfCharacters);
116 DALI_LOG_ERROR(" mTextUpdateInfo.mStartGlyphIndex = %u\n", impl.mTextUpdateInfo.mStartGlyphIndex);
117 DALI_LOG_ERROR(" mTextUpdateInfo.mStartLineIndex = %u\n", impl.mTextUpdateInfo.mStartLineIndex);
118 DALI_LOG_ERROR(" mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", impl.mTextUpdateInfo.mEstimatedNumberOfLines);
119 DALI_LOG_ERROR(" mTextUpdateInfo.mClearAll = %d\n", impl.mTextUpdateInfo.mClearAll);
120 DALI_LOG_ERROR(" mTextUpdateInfo.mFullRelayoutNeeded = %d\n", impl.mTextUpdateInfo.mFullRelayoutNeeded);
121 DALI_LOG_ERROR(" mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", impl.mTextUpdateInfo.mIsLastCharacterNewParagraph);
126 startIndex = impl.mTextUpdateInfo.mParagraphCharacterIndex;
128 if(impl.mTextUpdateInfo.mClearAll ||
129 (0u != paragraphCharacters))
131 impl.ClearModelData(startIndex, startIndex + ((paragraphCharacters > 0u) ? paragraphCharacters - 1u : 0u), operations);
134 impl.mTextUpdateInfo.mClearAll = false;
136 // Whether the model is updated.
137 bool updated = false;
139 Vector<LineBreakInfo>& lineBreakInfo = impl.mModel->mLogicalModel->mLineBreakInfo;
140 const Length requestedNumberOfCharacters = impl.mTextUpdateInfo.mRequestedNumberOfCharacters;
142 if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
144 // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
145 // calculate the bidirectional info for each 'paragraph'.
146 // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
147 // is not shaped together).
148 lineBreakInfo.Resize(numberOfCharacters, TextAbstraction::LINE_NO_BREAK);
150 SetLineBreakInfo(utf32Characters,
152 requestedNumberOfCharacters,
155 if(impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
156 impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED))
158 CharacterIndex end = startIndex + requestedNumberOfCharacters;
159 LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
161 for(CharacterIndex index = startIndex; index < end; index++)
163 CharacterIndex wordEnd = index;
164 while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK))
169 if((wordEnd + 1) == end) // add last char
174 Vector<bool> hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr);
176 for(CharacterIndex i = 0; i < (wordEnd - index); i++)
180 *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK;
188 // Create the paragraph info.
189 impl.mModel->mLogicalModel->CreateParagraphInfo(startIndex,
190 requestedNumberOfCharacters);
194 const bool getScripts = Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations);
195 const bool validateFonts = Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations);
197 Vector<ScriptRun>& scripts = impl.mModel->mLogicalModel->mScriptRuns;
198 Vector<FontRun>& validFonts = impl.mModel->mLogicalModel->mFontRuns;
200 if(getScripts || validateFonts)
202 // Validates the fonts assigned by the application or assigns default ones.
203 // It makes sure all the characters are going to be rendered by the correct font.
204 MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
208 // Retrieves the scripts used in the text.
209 multilanguageSupport.SetScripts(utf32Characters,
211 requestedNumberOfCharacters,
217 // Validate the fonts set through the mark-up string.
218 Vector<FontDescriptionRun>& fontDescriptionRuns = impl.mModel->mLogicalModel->mFontDescriptionRuns;
220 // Get the default font's description.
221 TextAbstraction::FontDescription defaultFontDescription;
222 TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * impl.GetFontSizeScale();
224 //Get the number of points per one unit of point-size
225 uint32_t numberOfPointsPerOneUnitOfPointSize = impl.mFontClient.GetNumberOfPointsPerOneUnitOfPointSize();
227 if(impl.IsShowingPlaceholderText() && impl.mEventData && (nullptr != impl.mEventData->mPlaceholderFont))
229 // If the placeholder font is set specifically, only placeholder font is changed.
230 defaultFontDescription = impl.mEventData->mPlaceholderFont->mFontDescription;
231 if(impl.mEventData->mPlaceholderFont->sizeDefined)
233 defaultPointSize = impl.mEventData->mPlaceholderFont->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
236 else if(nullptr != impl.mFontDefaults)
238 // Set the normal font and the placeholder font.
239 defaultFontDescription = impl.mFontDefaults->mFontDescription;
241 if(impl.mTextFitEnabled)
243 defaultPointSize = impl.mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize;
247 defaultPointSize = impl.mFontDefaults->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
251 // Validates the fonts. If there is a character with no assigned font it sets a default one.
252 // After this call, fonts are validated.
253 multilanguageSupport.ValidateFonts(utf32Characters,
256 defaultFontDescription,
259 requestedNumberOfCharacters,
265 Vector<Character> mirroredUtf32Characters;
266 bool textMirrored = false;
267 const Length numberOfParagraphs = impl.mModel->mLogicalModel->mParagraphInfo.Count();
268 if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
270 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = impl.mModel->mLogicalModel->mBidirectionalParagraphInfo;
271 bidirectionalInfo.Reserve(numberOfParagraphs);
273 // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
274 SetBidirectionalInfo(utf32Characters,
278 requestedNumberOfCharacters,
280 (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS),
281 impl.mLayoutDirection);
283 if(0u != bidirectionalInfo.Count())
285 // Only set the character directions if there is right to left characters.
286 Vector<CharacterDirection>& directions = impl.mModel->mLogicalModel->mCharacterDirections;
287 GetCharactersDirection(bidirectionalInfo,
290 requestedNumberOfCharacters,
293 // This paragraph has right to left text. Some characters may need to be mirrored.
294 // TODO: consider if the mirrored string can be stored as well.
296 textMirrored = GetMirroredText(utf32Characters,
300 requestedNumberOfCharacters,
301 mirroredUtf32Characters);
305 // There is no right to left characters. Clear the directions vector.
306 impl.mModel->mLogicalModel->mCharacterDirections.Clear();
311 Vector<GlyphInfo>& glyphs = impl.mModel->mVisualModel->mGlyphs;
312 Vector<CharacterIndex>& glyphsToCharactersMap = impl.mModel->mVisualModel->mGlyphsToCharacters;
313 Vector<Length>& charactersPerGlyph = impl.mModel->mVisualModel->mCharactersPerGlyph;
314 Vector<GlyphIndex> newParagraphGlyphs;
315 newParagraphGlyphs.Reserve(numberOfParagraphs);
317 const Length currentNumberOfGlyphs = glyphs.Count();
318 if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
320 const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
322 ShapeText(textToShape,
327 impl.mTextUpdateInfo.mStartGlyphIndex,
328 requestedNumberOfCharacters,
330 glyphsToCharactersMap,
334 // Create the 'number of glyphs' per character and the glyph to character conversion tables.
335 impl.mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
336 impl.mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
341 const Length numberOfGlyphs = static_cast<Length>(glyphs.Count()) - currentNumberOfGlyphs;
343 if(Controller::NO_OPERATION != (Controller::GET_GLYPH_METRICS & operations))
345 GlyphInfo* glyphsBuffer = glyphs.Begin();
346 impl.mMetrics->GetGlyphMetrics(glyphsBuffer + impl.mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs);
348 // Update the width and advance of all new paragraph characters.
349 for(Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it)
351 const GlyphIndex index = *it;
352 GlyphInfo& glyph = *(glyphsBuffer + index);
354 glyph.xBearing = 0.f;
361 if((nullptr != impl.mEventData) &&
362 impl.mEventData->mPreEditFlag &&
363 (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count()))
365 Dali::InputMethodContext::PreEditAttributeDataContainer attrs;
366 impl.mEventData->mInputMethodContext.GetPreeditStyle(attrs);
367 Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE;
369 // Check the type of preedit and run it.
370 for(Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++)
372 Dali::InputMethodContext::PreeditAttributeData attrData = *it;
373 DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex);
374 type = attrData.preeditType;
376 // Check the number of commit characters for the start position.
377 unsigned int numberOfCommit = impl.mEventData->mPrimaryCursorPosition - impl.mEventData->mPreEditLength;
378 Length numberOfIndices = attrData.endIndex - attrData.startIndex;
382 case Dali::InputMethodContext::PreeditStyle::UNDERLINE:
384 // Add the underline for the pre-edit text.
385 UnderlinedGlyphRun underlineRun;
386 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
387 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
388 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
390 //Mark-up processor case
391 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
392 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
394 impl.CopyUnderlinedFromLogicalToVisualModels(false);
398 case Dali::InputMethodContext::PreeditStyle::REVERSE:
400 Vector4 textColor = impl.mModel->mVisualModel->GetTextColor();
401 ColorRun backgroundColorRun;
402 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
403 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
404 backgroundColorRun.color = textColor;
405 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
407 Vector4 backgroundColor = impl.mModel->mVisualModel->GetBackgroundColor();
408 if(Dali::EqualsZero(backgroundColor.a)) // There is no text background color.
410 // Try use the control's background color.
411 if(nullptr != impl.mEditableControlInterface)
413 impl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
414 if(Dali::EqualsZero(backgroundColor.a)) // There is no control background color.
416 // Determines black or white color according to text color.
417 // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
418 float L = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b;
419 backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE;
424 Vector<ColorRun> colorRuns;
425 colorRuns.Resize(1u);
426 ColorRun& colorRun = *(colorRuns.Begin());
427 colorRun.color = backgroundColor;
428 colorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
429 colorRun.characterRun.numberOfCharacters = numberOfIndices;
430 impl.mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
432 //Mark-up processor case
433 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
434 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
436 impl.CopyUnderlinedFromLogicalToVisualModels(false);
440 case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
442 ColorRun backgroundColorRun;
443 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
444 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
445 backgroundColorRun.color = LIGHT_BLUE;
446 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
448 //Mark-up processor case
449 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
450 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
452 impl.CopyUnderlinedFromLogicalToVisualModels(false);
456 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
458 // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together.
459 ColorRun backgroundColorRun;
460 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
461 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
462 backgroundColorRun.color = BACKGROUND_SUB4;
463 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
465 UnderlinedGlyphRun underlineRun;
466 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
467 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
468 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
470 //Mark-up processor case
471 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
472 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
474 impl.CopyUnderlinedFromLogicalToVisualModels(false);
478 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2:
480 // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together.
481 ColorRun backgroundColorRun;
482 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
483 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
484 backgroundColorRun.color = BACKGROUND_SUB5;
485 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
487 UnderlinedGlyphRun underlineRun;
488 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
489 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
490 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
492 //Mark-up processor case
493 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
494 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
496 impl.CopyUnderlinedFromLogicalToVisualModels(false);
500 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3:
502 // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together.
503 ColorRun backgroundColorRun;
504 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
505 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
506 backgroundColorRun.color = BACKGROUND_SUB6;
507 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
509 UnderlinedGlyphRun underlineRun;
510 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
511 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
512 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
514 //Mark-up processor case
515 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
516 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
518 impl.CopyUnderlinedFromLogicalToVisualModels(false);
522 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4:
524 // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together.
525 ColorRun backgroundColorRun;
526 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
527 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
528 backgroundColorRun.color = BACKGROUND_SUB7;
529 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
531 UnderlinedGlyphRun underlineRun;
532 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
533 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
534 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
536 //Mark-up processor case
537 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
538 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
540 impl.CopyUnderlinedFromLogicalToVisualModels(false);
544 case Dali::InputMethodContext::PreeditStyle::NONE:
555 if(Controller::NO_OPERATION != (Controller::COLOR & operations))
557 // Set the color runs in glyphs.
558 SetColorSegmentationInfo(impl.mModel->mLogicalModel->mColorRuns,
559 impl.mModel->mVisualModel->mCharactersToGlyph,
560 impl.mModel->mVisualModel->mGlyphsPerCharacter,
562 impl.mTextUpdateInfo.mStartGlyphIndex,
563 requestedNumberOfCharacters,
564 impl.mModel->mVisualModel->mColors,
565 impl.mModel->mVisualModel->mColorIndices);
567 // Set the background color runs in glyphs.
568 SetColorSegmentationInfo(impl.mModel->mLogicalModel->mBackgroundColorRuns,
569 impl.mModel->mVisualModel->mCharactersToGlyph,
570 impl.mModel->mVisualModel->mGlyphsPerCharacter,
572 impl.mTextUpdateInfo.mStartGlyphIndex,
573 requestedNumberOfCharacters,
574 impl.mModel->mVisualModel->mBackgroundColors,
575 impl.mModel->mVisualModel->mBackgroundColorIndices);
580 if((Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) &&
581 !((nullptr != impl.mEventData) &&
582 impl.mEventData->mPreEditFlag &&
583 (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count())))
585 //Mark-up processor case
586 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
587 impl.mModel->mLogicalModel->mUnderlineRunsUpdated ||
588 impl.mModel->mLogicalModel->mCharacterSpacingRunsUpdated ||
589 impl.mModel->mLogicalModel->mStrikethroughRunsUpdated)
591 impl.CopyUnderlinedFromLogicalToVisualModels(true);
592 impl.CopyStrikethroughFromLogicalToVisualModels();
593 impl.CopyCharacterSpacingFromLogicalToVisualModels();
599 // The estimated number of lines. Used to avoid reallocations when layouting.
600 impl.mTextUpdateInfo.mEstimatedNumberOfLines = std::max(impl.mModel->mVisualModel->mLines.Count(), impl.mModel->mLogicalModel->mParagraphInfo.Count());
602 // Set the previous number of characters for the next time the text is updated.
603 impl.mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters;
608 } // namespace Dali::Toolkit::Text