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>
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)
75 if(impl.mEventData->mIsShowingPlaceholderText)
77 impl.mHiddenInput->InitPreviousTextCount();
81 impl.mHiddenInput->Substitute(srcCharacters, displayCharacters, impl.mEventData->mPrimaryCursorPosition);
86 Vector<Character>& utf32Characters = useHiddenText ? displayCharacters : srcCharacters;
87 const Length numberOfCharacters = utf32Characters.Count();
89 // Index to the first character of the first paragraph to be updated.
90 CharacterIndex startIndex = 0u;
91 // Number of characters of the paragraphs to be removed.
92 Length paragraphCharacters = 0u;
94 impl.CalculateTextUpdateIndices(paragraphCharacters);
96 // Check whether the indices for updating the text is valid
97 if(numberOfCharacters > 0u &&
98 (impl.mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters ||
99 impl.mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters))
101 std::string currentText;
102 Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText);
104 DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n");
105 DALI_LOG_ERROR("Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str());
107 // Dump mTextUpdateInfo
108 DALI_LOG_ERROR("Dump mTextUpdateInfo:\n");
109 DALI_LOG_ERROR(" mTextUpdateInfo.mCharacterIndex = %u\n", impl.mTextUpdateInfo.mCharacterIndex);
110 DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToRemove);
111 DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToAdd);
112 DALI_LOG_ERROR(" mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mPreviousNumberOfCharacters);
113 DALI_LOG_ERROR(" mTextUpdateInfo.mParagraphCharacterIndex = %u\n", impl.mTextUpdateInfo.mParagraphCharacterIndex);
114 DALI_LOG_ERROR(" mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mRequestedNumberOfCharacters);
115 DALI_LOG_ERROR(" mTextUpdateInfo.mStartGlyphIndex = %u\n", impl.mTextUpdateInfo.mStartGlyphIndex);
116 DALI_LOG_ERROR(" mTextUpdateInfo.mStartLineIndex = %u\n", impl.mTextUpdateInfo.mStartLineIndex);
117 DALI_LOG_ERROR(" mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", impl.mTextUpdateInfo.mEstimatedNumberOfLines);
118 DALI_LOG_ERROR(" mTextUpdateInfo.mClearAll = %d\n", impl.mTextUpdateInfo.mClearAll);
119 DALI_LOG_ERROR(" mTextUpdateInfo.mFullRelayoutNeeded = %d\n", impl.mTextUpdateInfo.mFullRelayoutNeeded);
120 DALI_LOG_ERROR(" mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", impl.mTextUpdateInfo.mIsLastCharacterNewParagraph);
125 startIndex = impl.mTextUpdateInfo.mParagraphCharacterIndex;
127 if(impl.mTextUpdateInfo.mClearAll ||
128 (0u != paragraphCharacters))
130 impl.ClearModelData(startIndex, startIndex + ((paragraphCharacters > 0u) ? paragraphCharacters - 1u : 0u), operations);
133 impl.mTextUpdateInfo.mClearAll = false;
135 // Whether the model is updated.
136 bool updated = false;
138 Vector<LineBreakInfo>& lineBreakInfo = impl.mModel->mLogicalModel->mLineBreakInfo;
139 const Length requestedNumberOfCharacters = impl.mTextUpdateInfo.mRequestedNumberOfCharacters;
141 if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
143 // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
144 // calculate the bidirectional info for each 'paragraph'.
145 // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
146 // is not shaped together).
147 lineBreakInfo.Resize(numberOfCharacters, TextAbstraction::LINE_NO_BREAK);
149 SetLineBreakInfo(utf32Characters,
151 requestedNumberOfCharacters,
154 if(impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
155 impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED))
157 CharacterIndex end = startIndex + requestedNumberOfCharacters;
158 LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
160 for(CharacterIndex index = startIndex; index < end; index++)
162 CharacterIndex wordEnd = index;
163 while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK))
168 if((wordEnd + 1) == end) // add last char
173 Vector<bool> hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr);
175 for(CharacterIndex i = 0; i < (wordEnd - index); i++)
179 *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK;
187 // Create the paragraph info.
188 impl.mModel->mLogicalModel->CreateParagraphInfo(startIndex,
189 requestedNumberOfCharacters);
193 const bool getScripts = Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations);
194 const bool validateFonts = Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations);
196 Vector<ScriptRun>& scripts = impl.mModel->mLogicalModel->mScriptRuns;
197 Vector<FontRun>& validFonts = impl.mModel->mLogicalModel->mFontRuns;
199 if(getScripts || validateFonts)
201 // Validates the fonts assigned by the application or assigns default ones.
202 // It makes sure all the characters are going to be rendered by the correct font.
203 MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
207 // Retrieves the scripts used in the text.
208 multilanguageSupport.SetScripts(utf32Characters,
210 requestedNumberOfCharacters,
216 // Validate the fonts set through the mark-up string.
217 Vector<FontDescriptionRun>& fontDescriptionRuns = impl.mModel->mLogicalModel->mFontDescriptionRuns;
219 // Get the default font's description.
220 TextAbstraction::FontDescription defaultFontDescription;
221 TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * impl.GetFontSizeScale();
223 //Get the number of points per one unit of point-size
224 uint32_t numberOfPointsPerOneUnitOfPointSize = impl.mFontClient.GetNumberOfPointsPerOneUnitOfPointSize();
226 if(impl.IsShowingPlaceholderText() && impl.mEventData && (nullptr != impl.mEventData->mPlaceholderFont))
228 // If the placeholder font is set specifically, only placeholder font is changed.
229 defaultFontDescription = impl.mEventData->mPlaceholderFont->mFontDescription;
230 if(impl.mEventData->mPlaceholderFont->sizeDefined)
232 defaultPointSize = impl.mEventData->mPlaceholderFont->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
235 else if(nullptr != impl.mFontDefaults)
237 // Set the normal font and the placeholder font.
238 defaultFontDescription = impl.mFontDefaults->mFontDescription;
240 if(impl.mTextFitEnabled)
242 defaultPointSize = impl.mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize;
246 defaultPointSize = impl.mFontDefaults->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
250 // Validates the fonts. If there is a character with no assigned font it sets a default one.
251 // After this call, fonts are validated.
252 multilanguageSupport.ValidateFonts(utf32Characters,
255 defaultFontDescription,
258 requestedNumberOfCharacters,
264 Vector<Character> mirroredUtf32Characters;
265 bool textMirrored = false;
266 const Length numberOfParagraphs = impl.mModel->mLogicalModel->mParagraphInfo.Count();
267 if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
269 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = impl.mModel->mLogicalModel->mBidirectionalParagraphInfo;
270 bidirectionalInfo.Reserve(numberOfParagraphs);
272 // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
273 SetBidirectionalInfo(utf32Characters,
277 requestedNumberOfCharacters,
279 (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS),
280 impl.mLayoutDirection);
282 if(0u != bidirectionalInfo.Count())
284 // Only set the character directions if there is right to left characters.
285 Vector<CharacterDirection>& directions = impl.mModel->mLogicalModel->mCharacterDirections;
286 GetCharactersDirection(bidirectionalInfo,
289 requestedNumberOfCharacters,
292 // This paragraph has right to left text. Some characters may need to be mirrored.
293 // TODO: consider if the mirrored string can be stored as well.
295 textMirrored = GetMirroredText(utf32Characters,
299 requestedNumberOfCharacters,
300 mirroredUtf32Characters);
304 // There is no right to left characters. Clear the directions vector.
305 impl.mModel->mLogicalModel->mCharacterDirections.Clear();
310 Vector<GlyphInfo>& glyphs = impl.mModel->mVisualModel->mGlyphs;
311 Vector<CharacterIndex>& glyphsToCharactersMap = impl.mModel->mVisualModel->mGlyphsToCharacters;
312 Vector<Length>& charactersPerGlyph = impl.mModel->mVisualModel->mCharactersPerGlyph;
313 Vector<GlyphIndex> newParagraphGlyphs;
314 newParagraphGlyphs.Reserve(numberOfParagraphs);
316 const Length currentNumberOfGlyphs = glyphs.Count();
317 if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
319 const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
321 ShapeText(textToShape,
326 impl.mTextUpdateInfo.mStartGlyphIndex,
327 requestedNumberOfCharacters,
329 glyphsToCharactersMap,
333 // Create the 'number of glyphs' per character and the glyph to character conversion tables.
334 impl.mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
335 impl.mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
340 const Length numberOfGlyphs = static_cast<Length>(glyphs.Count()) - currentNumberOfGlyphs;
342 if(Controller::NO_OPERATION != (Controller::GET_GLYPH_METRICS & operations))
344 GlyphInfo* glyphsBuffer = glyphs.Begin();
345 impl.mMetrics->GetGlyphMetrics(glyphsBuffer + impl.mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs);
347 // Update the width and advance of all new paragraph characters.
348 for(Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it)
350 const GlyphIndex index = *it;
351 GlyphInfo& glyph = *(glyphsBuffer + index);
353 glyph.xBearing = 0.f;
360 if((nullptr != impl.mEventData) &&
361 impl.mEventData->mPreEditFlag &&
362 (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count()))
364 Dali::InputMethodContext::PreEditAttributeDataContainer attrs;
365 impl.mEventData->mInputMethodContext.GetPreeditStyle(attrs);
366 Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE;
368 // Check the type of preedit and run it.
369 for(Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++)
371 Dali::InputMethodContext::PreeditAttributeData attrData = *it;
372 DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex);
373 type = attrData.preeditType;
375 // Check the number of commit characters for the start position.
376 unsigned int numberOfCommit = impl.mEventData->mPrimaryCursorPosition - impl.mEventData->mPreEditLength;
377 Length numberOfIndices = attrData.endIndex - attrData.startIndex;
381 case Dali::InputMethodContext::PreeditStyle::UNDERLINE:
383 // Add the underline for the pre-edit text.
384 UnderlinedGlyphRun underlineRun;
385 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
386 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
387 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
389 //Mark-up processor case
390 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
391 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
393 impl.CopyUnderlinedFromLogicalToVisualModels(false);
397 case Dali::InputMethodContext::PreeditStyle::REVERSE:
399 Vector4 textColor = impl.mModel->mVisualModel->GetTextColor();
400 ColorRun backgroundColorRun;
401 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
402 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
403 backgroundColorRun.color = textColor;
404 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
406 Vector4 backgroundColor = impl.mModel->mVisualModel->GetBackgroundColor();
407 if(backgroundColor.a == 0) // There is no text background color.
409 // Try use the control's background color.
410 if(nullptr != impl.mEditableControlInterface)
412 impl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
413 if(backgroundColor.a == 0) // There is no control background color.
415 // Determines black or white color according to text color.
416 // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
417 float L = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b;
418 backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE;
423 Vector<ColorRun> colorRuns;
424 colorRuns.Resize(1u);
425 ColorRun& colorRun = *(colorRuns.Begin());
426 colorRun.color = backgroundColor;
427 colorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
428 colorRun.characterRun.numberOfCharacters = numberOfIndices;
429 impl.mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
431 //Mark-up processor case
432 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
433 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
435 impl.CopyUnderlinedFromLogicalToVisualModels(false);
439 case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
441 ColorRun backgroundColorRun;
442 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
443 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
444 backgroundColorRun.color = LIGHT_BLUE;
445 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
447 //Mark-up processor case
448 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
449 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
451 impl.CopyUnderlinedFromLogicalToVisualModels(false);
455 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
457 // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together.
458 ColorRun backgroundColorRun;
459 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
460 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
461 backgroundColorRun.color = BACKGROUND_SUB4;
462 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
464 UnderlinedGlyphRun underlineRun;
465 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
466 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
467 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
469 //Mark-up processor case
470 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
471 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
473 impl.CopyUnderlinedFromLogicalToVisualModels(false);
477 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2:
479 // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together.
480 ColorRun backgroundColorRun;
481 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
482 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
483 backgroundColorRun.color = BACKGROUND_SUB5;
484 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
486 UnderlinedGlyphRun underlineRun;
487 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
488 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
489 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
491 //Mark-up processor case
492 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
493 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
495 impl.CopyUnderlinedFromLogicalToVisualModels(false);
499 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3:
501 // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together.
502 ColorRun backgroundColorRun;
503 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
504 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
505 backgroundColorRun.color = BACKGROUND_SUB6;
506 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
508 UnderlinedGlyphRun underlineRun;
509 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
510 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
511 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
513 //Mark-up processor case
514 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
515 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
517 impl.CopyUnderlinedFromLogicalToVisualModels(false);
521 case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4:
523 // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together.
524 ColorRun backgroundColorRun;
525 backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
526 backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
527 backgroundColorRun.color = BACKGROUND_SUB7;
528 impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
530 UnderlinedGlyphRun underlineRun;
531 underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit;
532 underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
533 impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
535 //Mark-up processor case
536 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
537 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
539 impl.CopyUnderlinedFromLogicalToVisualModels(false);
543 case Dali::InputMethodContext::PreeditStyle::NONE:
554 if(Controller::NO_OPERATION != (Controller::COLOR & operations))
556 // Set the color runs in glyphs.
557 SetColorSegmentationInfo(impl.mModel->mLogicalModel->mColorRuns,
558 impl.mModel->mVisualModel->mCharactersToGlyph,
559 impl.mModel->mVisualModel->mGlyphsPerCharacter,
561 impl.mTextUpdateInfo.mStartGlyphIndex,
562 requestedNumberOfCharacters,
563 impl.mModel->mVisualModel->mColors,
564 impl.mModel->mVisualModel->mColorIndices);
566 // Set the background color runs in glyphs.
567 SetColorSegmentationInfo(impl.mModel->mLogicalModel->mBackgroundColorRuns,
568 impl.mModel->mVisualModel->mCharactersToGlyph,
569 impl.mModel->mVisualModel->mGlyphsPerCharacter,
571 impl.mTextUpdateInfo.mStartGlyphIndex,
572 requestedNumberOfCharacters,
573 impl.mModel->mVisualModel->mBackgroundColors,
574 impl.mModel->mVisualModel->mBackgroundColorIndices);
579 if((Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) &&
580 !((nullptr != impl.mEventData) &&
581 impl.mEventData->mPreEditFlag &&
582 (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count())))
584 //Mark-up processor case
585 if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
586 impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
588 impl.CopyUnderlinedFromLogicalToVisualModels(true);
589 impl.CopyStrikethroughFromLogicalToVisualModels();
590 impl.CopyCharacterSpacingFromLogicalToVisualModels();
596 // The estimated number of lines. Used to avoid reallocations when layouting.
597 impl.mTextUpdateInfo.mEstimatedNumberOfLines = std::max(impl.mModel->mVisualModel->mLines.Count(), impl.mModel->mLogicalModel->mParagraphInfo.Count());
599 // Set the previous number of characters for the next time the text is updated.
600 impl.mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters;
605 } // namespace Dali::Toolkit::Text