Merge "WebView create a visual when it got a first frame" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-impl.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/text/text-controller-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/rendering/renderer.h>
24
25 // INTERNAL INCLUDES
26 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
27 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
28 #include <dali-toolkit/internal/text/bidirectional-support.h>
29 #include <dali-toolkit/internal/text/character-set-conversion.h>
30 #include <dali-toolkit/internal/text/color-segmentation.h>
31 #include <dali-toolkit/internal/text/cursor-helper-functions.h>
32 #include <dali-toolkit/internal/text/hyphenator.h>
33 #include <dali-toolkit/internal/text/multi-language-support.h>
34 #include <dali-toolkit/internal/text/segmentation.h>
35 #include <dali-toolkit/internal/text/shaper.h>
36 #include <dali-toolkit/internal/text/text-control-interface.h>
37 #include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
38 #include <dali-toolkit/internal/text/text-run-container.h>
39 #include <dali-toolkit/internal/text/text-selection-handle-controller.h>
40
41 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
42
43 using namespace Dali;
44
45 namespace
46 {
47 #if defined(DEBUG_ENABLED)
48 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
49 #endif
50
51 struct BackgroundVertex
52 {
53   Vector2 mPosition; ///< Vertex posiiton
54   Vector4 mColor;    ///< Vertex color
55 };
56
57 struct BackgroundMesh
58 {
59   Vector<BackgroundVertex> mVertices; ///< container of vertices
60   Vector<unsigned short>   mIndices;  ///< container of indices
61 };
62
63 const Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f);
64 const Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f);
65 const Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f);
66 const Dali::Vector4 BACKGROUND_SUB6(1.f, 0.5f, 0.5f, 1.f);
67 const Dali::Vector4 BACKGROUND_SUB7(1.f, 0.8f, 0.8f, 1.f);
68
69 } // namespace
70
71 namespace Dali
72 {
73 namespace Toolkit
74 {
75 namespace Text
76 {
77 EventData::EventData(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
78 : mDecorator(decorator),
79   mInputMethodContext(inputMethodContext),
80   mPlaceholderFont(NULL),
81   mPlaceholderTextActive(),
82   mPlaceholderTextInactive(),
83   mPlaceholderTextColor(0.8f, 0.8f, 0.8f, 0.8f), // This color has been published in the Public API (placeholder-properties.h).
84   mEventQueue(),
85   mInputStyleChangedQueue(),
86   mPreviousState(INACTIVE),
87   mState(INACTIVE),
88   mPrimaryCursorPosition(0u),
89   mLeftSelectionPosition(0u),
90   mRightSelectionPosition(0u),
91   mPreEditStartPosition(0u),
92   mPreEditLength(0u),
93   mCursorHookPositionX(0.f),
94   mDoubleTapAction(Controller::NoTextTap::NO_ACTION),
95   mLongPressAction(Controller::NoTextTap::SHOW_SELECTION_POPUP),
96   mIsShowingPlaceholderText(false),
97   mPreEditFlag(false),
98   mDecoratorUpdated(false),
99   mCursorBlinkEnabled(true),
100   mGrabHandleEnabled(true),
101   mGrabHandlePopupEnabled(true),
102   mSelectionEnabled(true),
103   mUpdateCursorHookPosition(false),
104   mUpdateCursorPosition(false),
105   mUpdateGrabHandlePosition(false),
106   mUpdateLeftSelectionPosition(false),
107   mUpdateRightSelectionPosition(false),
108   mIsLeftHandleSelected(false),
109   mIsRightHandleSelected(false),
110   mUpdateHighlightBox(false),
111   mScrollAfterUpdatePosition(false),
112   mScrollAfterDelete(false),
113   mAllTextSelected(false),
114   mUpdateInputStyle(false),
115   mPasswordInput(false),
116   mCheckScrollAmount(false),
117   mIsPlaceholderPixelSize(false),
118   mIsPlaceholderElideEnabled(false),
119   mPlaceholderEllipsisFlag(false),
120   mShiftSelectionFlag(true),
121   mUpdateAlignment(false),
122   mEditingEnabled(true)
123 {
124 }
125
126 bool Controller::Impl::ProcessInputEvents()
127 {
128   return ControllerImplEventHandler::ProcessInputEvents(*this);
129 }
130
131 void Controller::Impl::NotifyInputMethodContext()
132 {
133   if(mEventData && mEventData->mInputMethodContext)
134   {
135     CharacterIndex cursorPosition = GetLogicalCursorPosition();
136
137     const Length numberOfWhiteSpaces = GetNumberOfWhiteSpaces(0u);
138
139     // Update the cursor position by removing the initial white spaces.
140     if(cursorPosition < numberOfWhiteSpaces)
141     {
142       cursorPosition = 0u;
143     }
144     else
145     {
146       cursorPosition -= numberOfWhiteSpaces;
147     }
148
149     mEventData->mInputMethodContext.SetCursorPosition(cursorPosition);
150     mEventData->mInputMethodContext.NotifyCursorPosition();
151   }
152 }
153
154 void Controller::Impl::NotifyInputMethodContextMultiLineStatus()
155 {
156   if(mEventData && mEventData->mInputMethodContext)
157   {
158     Text::Layout::Engine::Type layout = mLayoutEngine.GetLayout();
159     mEventData->mInputMethodContext.NotifyTextInputMultiLine(layout == Text::Layout::Engine::MULTI_LINE_BOX);
160   }
161 }
162
163 CharacterIndex Controller::Impl::GetLogicalCursorPosition() const
164 {
165   CharacterIndex cursorPosition = 0u;
166
167   if(mEventData)
168   {
169     if((EventData::SELECTING == mEventData->mState) ||
170        (EventData::SELECTION_HANDLE_PANNING == mEventData->mState))
171     {
172       cursorPosition = std::min(mEventData->mRightSelectionPosition, mEventData->mLeftSelectionPosition);
173     }
174     else
175     {
176       cursorPosition = mEventData->mPrimaryCursorPosition;
177     }
178   }
179
180   return cursorPosition;
181 }
182
183 Length Controller::Impl::GetNumberOfWhiteSpaces(CharacterIndex index) const
184 {
185   Length numberOfWhiteSpaces = 0u;
186
187   // Get the buffer to the text.
188   Character* utf32CharacterBuffer = mModel->mLogicalModel->mText.Begin();
189
190   const Length totalNumberOfCharacters = mModel->mLogicalModel->mText.Count();
191   for(; index < totalNumberOfCharacters; ++index, ++numberOfWhiteSpaces)
192   {
193     if(!TextAbstraction::IsWhiteSpace(*(utf32CharacterBuffer + index)))
194     {
195       break;
196     }
197   }
198
199   return numberOfWhiteSpaces;
200 }
201
202 void Controller::Impl::GetText(CharacterIndex index, std::string& text) const
203 {
204   // Get the total number of characters.
205   Length numberOfCharacters = mModel->mLogicalModel->mText.Count();
206
207   // Retrieve the text.
208   if(0u != numberOfCharacters)
209   {
210     Utf32ToUtf8(mModel->mLogicalModel->mText.Begin() + index, numberOfCharacters - index, text);
211   }
212 }
213
214 void Controller::Impl::CalculateTextUpdateIndices(Length& numberOfCharacters)
215 {
216   mTextUpdateInfo.mParagraphCharacterIndex = 0u;
217   mTextUpdateInfo.mStartGlyphIndex         = 0u;
218   mTextUpdateInfo.mStartLineIndex          = 0u;
219   numberOfCharacters                       = 0u;
220
221   const Length numberOfParagraphs = mModel->mLogicalModel->mParagraphInfo.Count();
222   if(0u == numberOfParagraphs)
223   {
224     mTextUpdateInfo.mParagraphCharacterIndex = 0u;
225     numberOfCharacters                       = 0u;
226
227     mTextUpdateInfo.mRequestedNumberOfCharacters = mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
228
229     // Nothing else to do if there are no paragraphs.
230     return;
231   }
232
233   // Find the paragraphs to be updated.
234   Vector<ParagraphRunIndex> paragraphsToBeUpdated;
235   if(mTextUpdateInfo.mCharacterIndex >= mTextUpdateInfo.mPreviousNumberOfCharacters)
236   {
237     // Text is being added at the end of the current text.
238     if(mTextUpdateInfo.mIsLastCharacterNewParagraph)
239     {
240       // Text is being added in a new paragraph after the last character of the text.
241       mTextUpdateInfo.mParagraphCharacterIndex     = mTextUpdateInfo.mPreviousNumberOfCharacters;
242       numberOfCharacters                           = 0u;
243       mTextUpdateInfo.mRequestedNumberOfCharacters = mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
244
245       mTextUpdateInfo.mStartGlyphIndex = mModel->mVisualModel->mGlyphs.Count();
246       mTextUpdateInfo.mStartLineIndex  = mModel->mVisualModel->mLines.Count() - 1u;
247
248       // Nothing else to do;
249       return;
250     }
251
252     paragraphsToBeUpdated.PushBack(numberOfParagraphs - 1u);
253   }
254   else
255   {
256     Length numberOfCharactersToUpdate = 0u;
257     if(mTextUpdateInfo.mFullRelayoutNeeded)
258     {
259       numberOfCharactersToUpdate = mTextUpdateInfo.mPreviousNumberOfCharacters;
260     }
261     else
262     {
263       numberOfCharactersToUpdate = (mTextUpdateInfo.mNumberOfCharactersToRemove > 0u) ? mTextUpdateInfo.mNumberOfCharactersToRemove : 1u;
264     }
265     mModel->mLogicalModel->FindParagraphs(mTextUpdateInfo.mCharacterIndex,
266                                           numberOfCharactersToUpdate,
267                                           paragraphsToBeUpdated);
268   }
269
270   if(0u != paragraphsToBeUpdated.Count())
271   {
272     const ParagraphRunIndex firstParagraphIndex = *(paragraphsToBeUpdated.Begin());
273     const ParagraphRun&     firstParagraph      = *(mModel->mLogicalModel->mParagraphInfo.Begin() + firstParagraphIndex);
274     mTextUpdateInfo.mParagraphCharacterIndex    = firstParagraph.characterRun.characterIndex;
275
276     ParagraphRunIndex   lastParagraphIndex = *(paragraphsToBeUpdated.End() - 1u);
277     const ParagraphRun& lastParagraph      = *(mModel->mLogicalModel->mParagraphInfo.Begin() + lastParagraphIndex);
278
279     if((mTextUpdateInfo.mNumberOfCharactersToRemove > 0u) &&                                           // Some character are removed.
280        (lastParagraphIndex < numberOfParagraphs - 1u) &&                                               // There is a next paragraph.
281        ((lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters) == // The last removed character is the new paragraph character.
282         (mTextUpdateInfo.mCharacterIndex + mTextUpdateInfo.mNumberOfCharactersToRemove)))
283     {
284       // The new paragraph character of the last updated paragraph has been removed so is going to be merged with the next one.
285       const ParagraphRun& lastParagraph = *(mModel->mLogicalModel->mParagraphInfo.Begin() + lastParagraphIndex + 1u);
286
287       numberOfCharacters = lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters - mTextUpdateInfo.mParagraphCharacterIndex;
288     }
289     else
290     {
291       numberOfCharacters = lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters - mTextUpdateInfo.mParagraphCharacterIndex;
292     }
293   }
294
295   mTextUpdateInfo.mRequestedNumberOfCharacters = numberOfCharacters + mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
296   mTextUpdateInfo.mStartGlyphIndex             = *(mModel->mVisualModel->mCharactersToGlyph.Begin() + mTextUpdateInfo.mParagraphCharacterIndex);
297 }
298
299 void Controller::Impl::ClearFullModelData(OperationsMask operations)
300 {
301   if(NO_OPERATION != (GET_LINE_BREAKS & operations))
302   {
303     mModel->mLogicalModel->mLineBreakInfo.Clear();
304     mModel->mLogicalModel->mParagraphInfo.Clear();
305   }
306
307   if(NO_OPERATION != (GET_SCRIPTS & operations))
308   {
309     mModel->mLogicalModel->mScriptRuns.Clear();
310   }
311
312   if(NO_OPERATION != (VALIDATE_FONTS & operations))
313   {
314     mModel->mLogicalModel->mFontRuns.Clear();
315   }
316
317   if(0u != mModel->mLogicalModel->mBidirectionalParagraphInfo.Count())
318   {
319     if(NO_OPERATION != (BIDI_INFO & operations))
320     {
321       mModel->mLogicalModel->mBidirectionalParagraphInfo.Clear();
322       mModel->mLogicalModel->mCharacterDirections.Clear();
323     }
324
325     if(NO_OPERATION != (REORDER & operations))
326     {
327       // Free the allocated memory used to store the conversion table in the bidirectional line info run.
328       for(Vector<BidirectionalLineInfoRun>::Iterator it    = mModel->mLogicalModel->mBidirectionalLineInfo.Begin(),
329                                                      endIt = mModel->mLogicalModel->mBidirectionalLineInfo.End();
330           it != endIt;
331           ++it)
332       {
333         BidirectionalLineInfoRun& bidiLineInfo = *it;
334
335         free(bidiLineInfo.visualToLogicalMap);
336         bidiLineInfo.visualToLogicalMap = NULL;
337       }
338       mModel->mLogicalModel->mBidirectionalLineInfo.Clear();
339     }
340   }
341
342   if(NO_OPERATION != (SHAPE_TEXT & operations))
343   {
344     mModel->mVisualModel->mGlyphs.Clear();
345     mModel->mVisualModel->mGlyphsToCharacters.Clear();
346     mModel->mVisualModel->mCharactersToGlyph.Clear();
347     mModel->mVisualModel->mCharactersPerGlyph.Clear();
348     mModel->mVisualModel->mGlyphsPerCharacter.Clear();
349     mModel->mVisualModel->mGlyphPositions.Clear();
350   }
351
352   if(NO_OPERATION != (LAYOUT & operations))
353   {
354     mModel->mVisualModel->mLines.Clear();
355   }
356
357   if(NO_OPERATION != (COLOR & operations))
358   {
359     mModel->mVisualModel->mColorIndices.Clear();
360     mModel->mVisualModel->mBackgroundColorIndices.Clear();
361   }
362 }
363
364 void Controller::Impl::ClearCharacterModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations)
365 {
366   const CharacterIndex endIndexPlusOne = endIndex + 1u;
367
368   if(NO_OPERATION != (GET_LINE_BREAKS & operations))
369   {
370     // Clear the line break info.
371     LineBreakInfo* lineBreakInfoBuffer = mModel->mLogicalModel->mLineBreakInfo.Begin();
372
373     mModel->mLogicalModel->mLineBreakInfo.Erase(lineBreakInfoBuffer + startIndex,
374                                                 lineBreakInfoBuffer + endIndexPlusOne);
375
376     // Clear the paragraphs.
377     ClearCharacterRuns(startIndex,
378                        endIndex,
379                        mModel->mLogicalModel->mParagraphInfo);
380   }
381
382   if(NO_OPERATION != (GET_SCRIPTS & operations))
383   {
384     // Clear the scripts.
385     ClearCharacterRuns(startIndex,
386                        endIndex,
387                        mModel->mLogicalModel->mScriptRuns);
388   }
389
390   if(NO_OPERATION != (VALIDATE_FONTS & operations))
391   {
392     // Clear the fonts.
393     ClearCharacterRuns(startIndex,
394                        endIndex,
395                        mModel->mLogicalModel->mFontRuns);
396   }
397
398   if(0u != mModel->mLogicalModel->mBidirectionalParagraphInfo.Count())
399   {
400     if(NO_OPERATION != (BIDI_INFO & operations))
401     {
402       // Clear the bidirectional paragraph info.
403       ClearCharacterRuns(startIndex,
404                          endIndex,
405                          mModel->mLogicalModel->mBidirectionalParagraphInfo);
406
407       // Clear the character's directions.
408       CharacterDirection* characterDirectionsBuffer = mModel->mLogicalModel->mCharacterDirections.Begin();
409
410       mModel->mLogicalModel->mCharacterDirections.Erase(characterDirectionsBuffer + startIndex,
411                                                         characterDirectionsBuffer + endIndexPlusOne);
412     }
413
414     if(NO_OPERATION != (REORDER & operations))
415     {
416       uint32_t startRemoveIndex = mModel->mLogicalModel->mBidirectionalLineInfo.Count();
417       uint32_t endRemoveIndex   = startRemoveIndex;
418       ClearCharacterRuns(startIndex,
419                          endIndex,
420                          mModel->mLogicalModel->mBidirectionalLineInfo,
421                          startRemoveIndex,
422                          endRemoveIndex);
423
424       BidirectionalLineInfoRun* bidirectionalLineInfoBuffer = mModel->mLogicalModel->mBidirectionalLineInfo.Begin();
425
426       // Free the allocated memory used to store the conversion table in the bidirectional line info run.
427       for(Vector<BidirectionalLineInfoRun>::Iterator it    = bidirectionalLineInfoBuffer + startRemoveIndex,
428                                                      endIt = bidirectionalLineInfoBuffer + endRemoveIndex;
429           it != endIt;
430           ++it)
431       {
432         BidirectionalLineInfoRun& bidiLineInfo = *it;
433
434         free(bidiLineInfo.visualToLogicalMap);
435         bidiLineInfo.visualToLogicalMap = NULL;
436       }
437
438       mModel->mLogicalModel->mBidirectionalLineInfo.Erase(bidirectionalLineInfoBuffer + startRemoveIndex,
439                                                           bidirectionalLineInfoBuffer + endRemoveIndex);
440     }
441   }
442 }
443
444 void Controller::Impl::ClearGlyphModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations)
445 {
446   const CharacterIndex endIndexPlusOne           = endIndex + 1u;
447   const Length         numberOfCharactersRemoved = endIndexPlusOne - startIndex;
448
449   // Convert the character index to glyph index before deleting the character to glyph and the glyphs per character buffers.
450   GlyphIndex* charactersToGlyphBuffer  = mModel->mVisualModel->mCharactersToGlyph.Begin();
451   Length*     glyphsPerCharacterBuffer = mModel->mVisualModel->mGlyphsPerCharacter.Begin();
452
453   const GlyphIndex endGlyphIndexPlusOne  = *(charactersToGlyphBuffer + endIndex) + *(glyphsPerCharacterBuffer + endIndex);
454   const Length     numberOfGlyphsRemoved = endGlyphIndexPlusOne - mTextUpdateInfo.mStartGlyphIndex;
455
456   if(NO_OPERATION != (SHAPE_TEXT & operations))
457   {
458     // Update the character to glyph indices.
459     for(Vector<GlyphIndex>::Iterator it    = charactersToGlyphBuffer + endIndexPlusOne,
460                                      endIt = charactersToGlyphBuffer + mModel->mVisualModel->mCharactersToGlyph.Count();
461         it != endIt;
462         ++it)
463     {
464       CharacterIndex& index = *it;
465       index -= numberOfGlyphsRemoved;
466     }
467
468     // Clear the character to glyph conversion table.
469     mModel->mVisualModel->mCharactersToGlyph.Erase(charactersToGlyphBuffer + startIndex,
470                                                    charactersToGlyphBuffer + endIndexPlusOne);
471
472     // Clear the glyphs per character table.
473     mModel->mVisualModel->mGlyphsPerCharacter.Erase(glyphsPerCharacterBuffer + startIndex,
474                                                     glyphsPerCharacterBuffer + endIndexPlusOne);
475
476     // Clear the glyphs buffer.
477     GlyphInfo* glyphsBuffer = mModel->mVisualModel->mGlyphs.Begin();
478     mModel->mVisualModel->mGlyphs.Erase(glyphsBuffer + mTextUpdateInfo.mStartGlyphIndex,
479                                         glyphsBuffer + endGlyphIndexPlusOne);
480
481     CharacterIndex* glyphsToCharactersBuffer = mModel->mVisualModel->mGlyphsToCharacters.Begin();
482
483     // Update the glyph to character indices.
484     for(Vector<CharacterIndex>::Iterator it    = glyphsToCharactersBuffer + endGlyphIndexPlusOne,
485                                          endIt = glyphsToCharactersBuffer + mModel->mVisualModel->mGlyphsToCharacters.Count();
486         it != endIt;
487         ++it)
488     {
489       CharacterIndex& index = *it;
490       index -= numberOfCharactersRemoved;
491     }
492
493     // Clear the glyphs to characters buffer.
494     mModel->mVisualModel->mGlyphsToCharacters.Erase(glyphsToCharactersBuffer + mTextUpdateInfo.mStartGlyphIndex,
495                                                     glyphsToCharactersBuffer + endGlyphIndexPlusOne);
496
497     // Clear the characters per glyph buffer.
498     Length* charactersPerGlyphBuffer = mModel->mVisualModel->mCharactersPerGlyph.Begin();
499     mModel->mVisualModel->mCharactersPerGlyph.Erase(charactersPerGlyphBuffer + mTextUpdateInfo.mStartGlyphIndex,
500                                                     charactersPerGlyphBuffer + endGlyphIndexPlusOne);
501
502     // Clear the positions buffer.
503     Vector2* positionsBuffer = mModel->mVisualModel->mGlyphPositions.Begin();
504     mModel->mVisualModel->mGlyphPositions.Erase(positionsBuffer + mTextUpdateInfo.mStartGlyphIndex,
505                                                 positionsBuffer + endGlyphIndexPlusOne);
506   }
507
508   if(NO_OPERATION != (LAYOUT & operations))
509   {
510     // Clear the lines.
511     uint32_t startRemoveIndex = mModel->mVisualModel->mLines.Count();
512     uint32_t endRemoveIndex   = startRemoveIndex;
513     ClearCharacterRuns(startIndex,
514                        endIndex,
515                        mModel->mVisualModel->mLines,
516                        startRemoveIndex,
517                        endRemoveIndex);
518
519     // Will update the glyph runs.
520     startRemoveIndex = mModel->mVisualModel->mLines.Count();
521     endRemoveIndex   = startRemoveIndex;
522     ClearGlyphRuns(mTextUpdateInfo.mStartGlyphIndex,
523                    endGlyphIndexPlusOne - 1u,
524                    mModel->mVisualModel->mLines,
525                    startRemoveIndex,
526                    endRemoveIndex);
527
528     // Set the line index from where to insert the new laid-out lines.
529     mTextUpdateInfo.mStartLineIndex = startRemoveIndex;
530
531     LineRun* linesBuffer = mModel->mVisualModel->mLines.Begin();
532     mModel->mVisualModel->mLines.Erase(linesBuffer + startRemoveIndex,
533                                        linesBuffer + endRemoveIndex);
534   }
535
536   if(NO_OPERATION != (COLOR & operations))
537   {
538     if(0u != mModel->mVisualModel->mColorIndices.Count())
539     {
540       ColorIndex* colorIndexBuffer = mModel->mVisualModel->mColorIndices.Begin();
541       mModel->mVisualModel->mColorIndices.Erase(colorIndexBuffer + mTextUpdateInfo.mStartGlyphIndex,
542                                                 colorIndexBuffer + endGlyphIndexPlusOne);
543     }
544
545     if(0u != mModel->mVisualModel->mBackgroundColorIndices.Count())
546     {
547       ColorIndex* backgroundColorIndexBuffer = mModel->mVisualModel->mBackgroundColorIndices.Begin();
548       mModel->mVisualModel->mBackgroundColorIndices.Erase(backgroundColorIndexBuffer + mTextUpdateInfo.mStartGlyphIndex,
549                                                           backgroundColorIndexBuffer + endGlyphIndexPlusOne);
550     }
551   }
552 }
553
554 void Controller::Impl::ClearModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations)
555 {
556   if(mTextUpdateInfo.mClearAll ||
557      ((0u == startIndex) &&
558       (mTextUpdateInfo.mPreviousNumberOfCharacters == endIndex + 1u)))
559   {
560     ClearFullModelData(operations);
561   }
562   else
563   {
564     // Clear the model data related with characters.
565     ClearCharacterModelData(startIndex, endIndex, operations);
566
567     // Clear the model data related with glyphs.
568     ClearGlyphModelData(startIndex, endIndex, operations);
569   }
570
571   // The estimated number of lines. Used to avoid reallocations when layouting.
572   mTextUpdateInfo.mEstimatedNumberOfLines = std::max(mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count());
573
574   mModel->mVisualModel->ClearCaches();
575 }
576
577 bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
578 {
579   DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel\n");
580
581   // Calculate the operations to be done.
582   const OperationsMask operations = static_cast<OperationsMask>(mOperationsPending & operationsRequired);
583
584   if(NO_OPERATION == operations)
585   {
586     // Nothing to do if no operations are pending and required.
587     return false;
588   }
589
590   Vector<Character>& srcCharacters = mModel->mLogicalModel->mText;
591   Vector<Character>  displayCharacters;
592   bool               useHiddenText = false;
593   if(mHiddenInput && mEventData != nullptr && !mEventData->mIsShowingPlaceholderText)
594   {
595     mHiddenInput->Substitute(srcCharacters, displayCharacters);
596     useHiddenText = true;
597   }
598
599   Vector<Character>& utf32Characters    = useHiddenText ? displayCharacters : srcCharacters;
600   const Length       numberOfCharacters = utf32Characters.Count();
601
602   // Index to the first character of the first paragraph to be updated.
603   CharacterIndex startIndex = 0u;
604   // Number of characters of the paragraphs to be removed.
605   Length paragraphCharacters = 0u;
606
607   CalculateTextUpdateIndices(paragraphCharacters);
608
609   // Check whether the indices for updating the text is valid
610   if(numberOfCharacters > 0u &&
611      (mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters ||
612       mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters))
613   {
614     std::string currentText;
615     Utf32ToUtf8(mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText);
616
617     DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n");
618     DALI_LOG_ERROR("Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str());
619
620     // Dump mTextUpdateInfo
621     DALI_LOG_ERROR("Dump mTextUpdateInfo:\n");
622     DALI_LOG_ERROR("     mTextUpdateInfo.mCharacterIndex = %u\n", mTextUpdateInfo.mCharacterIndex);
623     DALI_LOG_ERROR("     mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", mTextUpdateInfo.mNumberOfCharactersToRemove);
624     DALI_LOG_ERROR("     mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", mTextUpdateInfo.mNumberOfCharactersToAdd);
625     DALI_LOG_ERROR("     mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", mTextUpdateInfo.mPreviousNumberOfCharacters);
626     DALI_LOG_ERROR("     mTextUpdateInfo.mParagraphCharacterIndex = %u\n", mTextUpdateInfo.mParagraphCharacterIndex);
627     DALI_LOG_ERROR("     mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", mTextUpdateInfo.mRequestedNumberOfCharacters);
628     DALI_LOG_ERROR("     mTextUpdateInfo.mStartGlyphIndex = %u\n", mTextUpdateInfo.mStartGlyphIndex);
629     DALI_LOG_ERROR("     mTextUpdateInfo.mStartLineIndex = %u\n", mTextUpdateInfo.mStartLineIndex);
630     DALI_LOG_ERROR("     mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", mTextUpdateInfo.mEstimatedNumberOfLines);
631     DALI_LOG_ERROR("     mTextUpdateInfo.mClearAll = %d\n", mTextUpdateInfo.mClearAll);
632     DALI_LOG_ERROR("     mTextUpdateInfo.mFullRelayoutNeeded = %d\n", mTextUpdateInfo.mFullRelayoutNeeded);
633     DALI_LOG_ERROR("     mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", mTextUpdateInfo.mIsLastCharacterNewParagraph);
634
635     return false;
636   }
637
638   startIndex = mTextUpdateInfo.mParagraphCharacterIndex;
639
640   if(mTextUpdateInfo.mClearAll ||
641      (0u != paragraphCharacters))
642   {
643     ClearModelData(startIndex, startIndex + ((paragraphCharacters > 0u) ? paragraphCharacters - 1u : 0u), operations);
644   }
645
646   mTextUpdateInfo.mClearAll = false;
647
648   // Whether the model is updated.
649   bool updated = false;
650
651   Vector<LineBreakInfo>& lineBreakInfo               = mModel->mLogicalModel->mLineBreakInfo;
652   const Length           requestedNumberOfCharacters = mTextUpdateInfo.mRequestedNumberOfCharacters;
653
654   if(NO_OPERATION != (GET_LINE_BREAKS & operations))
655   {
656     // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
657     // calculate the bidirectional info for each 'paragraph'.
658     // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
659     // is not shaped together).
660     lineBreakInfo.Resize(numberOfCharacters, TextAbstraction::LINE_NO_BREAK);
661
662     SetLineBreakInfo(utf32Characters,
663                      startIndex,
664                      requestedNumberOfCharacters,
665                      lineBreakInfo);
666
667     if(mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
668        mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED))
669     {
670       CharacterIndex end                 = startIndex + requestedNumberOfCharacters;
671       LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
672
673       for(CharacterIndex index = startIndex; index < end; index++)
674       {
675         CharacterIndex wordEnd = index;
676         while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK))
677         {
678           wordEnd++;
679         }
680
681         if((wordEnd + 1) == end) // add last char
682         {
683           wordEnd++;
684         }
685
686         Vector<bool> hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr);
687
688         for(CharacterIndex i = 0; i < (wordEnd - index); i++)
689         {
690           if(hyphens[i])
691           {
692             *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK;
693           }
694         }
695
696         index = wordEnd;
697       }
698     }
699
700     // Create the paragraph info.
701     mModel->mLogicalModel->CreateParagraphInfo(startIndex,
702                                                requestedNumberOfCharacters);
703     updated = true;
704   }
705
706   const bool getScripts    = NO_OPERATION != (GET_SCRIPTS & operations);
707   const bool validateFonts = NO_OPERATION != (VALIDATE_FONTS & operations);
708
709   Vector<ScriptRun>& scripts    = mModel->mLogicalModel->mScriptRuns;
710   Vector<FontRun>&   validFonts = mModel->mLogicalModel->mFontRuns;
711
712   if(getScripts || validateFonts)
713   {
714     // Validates the fonts assigned by the application or assigns default ones.
715     // It makes sure all the characters are going to be rendered by the correct font.
716     MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
717
718     if(getScripts)
719     {
720       // Retrieves the scripts used in the text.
721       multilanguageSupport.SetScripts(utf32Characters,
722                                       startIndex,
723                                       requestedNumberOfCharacters,
724                                       scripts);
725     }
726
727     if(validateFonts)
728     {
729       // Validate the fonts set through the mark-up string.
730       Vector<FontDescriptionRun>& fontDescriptionRuns = mModel->mLogicalModel->mFontDescriptionRuns;
731
732       // Get the default font's description.
733       TextAbstraction::FontDescription defaultFontDescription;
734       TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * mFontSizeScale;
735
736       //Get the number of points per one unit of point-size
737       uint32_t numberOfPointsPerOneUnitOfPointSize = mFontClient.GetNumberOfPointsPerOneUnitOfPointSize();
738
739       if(IsShowingPlaceholderText() && mEventData && (nullptr != mEventData->mPlaceholderFont))
740       {
741         // If the placeholder font is set specifically, only placeholder font is changed.
742         defaultFontDescription = mEventData->mPlaceholderFont->mFontDescription;
743         if(mEventData->mPlaceholderFont->sizeDefined)
744         {
745           defaultPointSize = mEventData->mPlaceholderFont->mDefaultPointSize * mFontSizeScale * numberOfPointsPerOneUnitOfPointSize;
746         }
747       }
748       else if(nullptr != mFontDefaults)
749       {
750         // Set the normal font and the placeholder font.
751         defaultFontDescription = mFontDefaults->mFontDescription;
752
753         if(mTextFitEnabled)
754         {
755           defaultPointSize = mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize;
756         }
757         else
758         {
759           defaultPointSize = mFontDefaults->mDefaultPointSize * mFontSizeScale * numberOfPointsPerOneUnitOfPointSize;
760         }
761       }
762
763       // Validates the fonts. If there is a character with no assigned font it sets a default one.
764       // After this call, fonts are validated.
765       multilanguageSupport.ValidateFonts(utf32Characters,
766                                          scripts,
767                                          fontDescriptionRuns,
768                                          defaultFontDescription,
769                                          defaultPointSize,
770                                          startIndex,
771                                          requestedNumberOfCharacters,
772                                          validFonts);
773     }
774     updated = true;
775   }
776
777   Vector<Character> mirroredUtf32Characters;
778   bool              textMirrored       = false;
779   const Length      numberOfParagraphs = mModel->mLogicalModel->mParagraphInfo.Count();
780   if(NO_OPERATION != (BIDI_INFO & operations))
781   {
782     Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mModel->mLogicalModel->mBidirectionalParagraphInfo;
783     bidirectionalInfo.Reserve(numberOfParagraphs);
784
785     // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
786     SetBidirectionalInfo(utf32Characters,
787                          scripts,
788                          lineBreakInfo,
789                          startIndex,
790                          requestedNumberOfCharacters,
791                          bidirectionalInfo,
792                          mModel->mMatchSystemLanguageDirection,
793                          mLayoutDirection);
794
795     if(0u != bidirectionalInfo.Count())
796     {
797       // Only set the character directions if there is right to left characters.
798       Vector<CharacterDirection>& directions = mModel->mLogicalModel->mCharacterDirections;
799       GetCharactersDirection(bidirectionalInfo,
800                              numberOfCharacters,
801                              startIndex,
802                              requestedNumberOfCharacters,
803                              directions);
804
805       // This paragraph has right to left text. Some characters may need to be mirrored.
806       // TODO: consider if the mirrored string can be stored as well.
807
808       textMirrored = GetMirroredText(utf32Characters,
809                                      directions,
810                                      bidirectionalInfo,
811                                      startIndex,
812                                      requestedNumberOfCharacters,
813                                      mirroredUtf32Characters);
814     }
815     else
816     {
817       // There is no right to left characters. Clear the directions vector.
818       mModel->mLogicalModel->mCharacterDirections.Clear();
819     }
820     updated = true;
821   }
822
823   Vector<GlyphInfo>&      glyphs                = mModel->mVisualModel->mGlyphs;
824   Vector<CharacterIndex>& glyphsToCharactersMap = mModel->mVisualModel->mGlyphsToCharacters;
825   Vector<Length>&         charactersPerGlyph    = mModel->mVisualModel->mCharactersPerGlyph;
826   Vector<GlyphIndex>      newParagraphGlyphs;
827   newParagraphGlyphs.Reserve(numberOfParagraphs);
828
829   const Length currentNumberOfGlyphs = glyphs.Count();
830   if(NO_OPERATION != (SHAPE_TEXT & operations))
831   {
832     const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
833     // Shapes the text.
834     ShapeText(textToShape,
835               lineBreakInfo,
836               scripts,
837               validFonts,
838               startIndex,
839               mTextUpdateInfo.mStartGlyphIndex,
840               requestedNumberOfCharacters,
841               glyphs,
842               glyphsToCharactersMap,
843               charactersPerGlyph,
844               newParagraphGlyphs);
845
846     // Create the 'number of glyphs' per character and the glyph to character conversion tables.
847     mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
848     mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
849
850     updated = true;
851   }
852
853   const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs;
854
855   if(NO_OPERATION != (GET_GLYPH_METRICS & operations))
856   {
857     GlyphInfo* glyphsBuffer = glyphs.Begin();
858     mMetrics->GetGlyphMetrics(glyphsBuffer + mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs);
859
860     // Update the width and advance of all new paragraph characters.
861     for(Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it)
862     {
863       const GlyphIndex index = *it;
864       GlyphInfo&       glyph = *(glyphsBuffer + index);
865
866       glyph.xBearing = 0.f;
867       glyph.width    = 0.f;
868       glyph.advance  = 0.f;
869     }
870     updated = true;
871   }
872
873   if((nullptr != mEventData) &&
874      mEventData->mPreEditFlag &&
875      (0u != mModel->mVisualModel->mCharactersToGlyph.Count()))
876   {
877     Dali::InputMethodContext::PreEditAttributeDataContainer attrs;
878     mEventData->mInputMethodContext.GetPreeditStyle(attrs);
879     Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE;
880
881     // Check the type of preedit and run it.
882     for(Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++)
883     {
884       Dali::InputMethodContext::PreeditAttributeData attrData = *it;
885       DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d  start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex);
886       type = attrData.preeditType;
887
888       // Check the number of commit characters for the start position.
889       unsigned int numberOfCommit  = mEventData->mPrimaryCursorPosition - mEventData->mPreEditLength;
890       Length       numberOfIndices = attrData.endIndex - attrData.startIndex;
891
892       switch(type)
893       {
894         case Dali::InputMethodContext::PreeditStyle::UNDERLINE:
895         {
896           // Add the underline for the pre-edit text.
897           GlyphRun underlineRun;
898           underlineRun.glyphIndex     = attrData.startIndex + numberOfCommit;
899           underlineRun.numberOfGlyphs = numberOfIndices;
900           mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
901
902           //Mark-up processor case
903           if(mModel->mVisualModel->IsMarkupProcessorEnabled())
904           {
905             CopyUnderlinedFromLogicalToVisualModels(false);
906           }
907           break;
908         }
909         case Dali::InputMethodContext::PreeditStyle::REVERSE:
910         {
911           Vector4  textColor = mModel->mVisualModel->GetTextColor();
912           ColorRun backgroundColorRun;
913           backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
914           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
915           backgroundColorRun.color                           = textColor;
916           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
917
918           Vector4          backgroundColor = mModel->mVisualModel->GetBackgroundColor();
919           Vector<ColorRun> colorRuns;
920           colorRuns.Resize(1u);
921           ColorRun& colorRun                       = *(colorRuns.Begin());
922           colorRun.color                           = backgroundColor;
923           colorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
924           colorRun.characterRun.numberOfCharacters = numberOfIndices;
925           mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
926
927           //Mark-up processor case
928           if(mModel->mVisualModel->IsMarkupProcessorEnabled())
929           {
930             CopyUnderlinedFromLogicalToVisualModels(false);
931           }
932           break;
933         }
934         case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
935         {
936           ColorRun backgroundColorRun;
937           backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
938           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
939           backgroundColorRun.color                           = LIGHT_BLUE;
940           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
941
942           //Mark-up processor case
943           if(mModel->mVisualModel->IsMarkupProcessorEnabled())
944           {
945             CopyUnderlinedFromLogicalToVisualModels(false);
946           }
947           break;
948         }
949         case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
950         {
951           // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together.
952           ColorRun backgroundColorRun;
953           backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
954           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
955           backgroundColorRun.color                           = BACKGROUND_SUB4;
956           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
957
958           GlyphRun underlineRun;
959           underlineRun.glyphIndex     = attrData.startIndex + numberOfCommit;
960           underlineRun.numberOfGlyphs = numberOfIndices;
961           mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
962
963           //Mark-up processor case
964           if(mModel->mVisualModel->IsMarkupProcessorEnabled())
965           {
966             CopyUnderlinedFromLogicalToVisualModels(false);
967           }
968           break;
969         }
970         case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2:
971         {
972           // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together.
973           ColorRun backgroundColorRun;
974           backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
975           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
976           backgroundColorRun.color                           = BACKGROUND_SUB5;
977           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
978
979           GlyphRun underlineRun;
980           underlineRun.glyphIndex     = attrData.startIndex + numberOfCommit;
981           underlineRun.numberOfGlyphs = numberOfIndices;
982           mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
983
984           //Mark-up processor case
985           if(mModel->mVisualModel->IsMarkupProcessorEnabled())
986           {
987             CopyUnderlinedFromLogicalToVisualModels(false);
988           }
989           break;
990         }
991         case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3:
992         {
993           // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together.
994           ColorRun backgroundColorRun;
995           backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
996           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
997           backgroundColorRun.color                           = BACKGROUND_SUB6;
998           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
999
1000           GlyphRun underlineRun;
1001           underlineRun.glyphIndex     = attrData.startIndex + numberOfCommit;
1002           underlineRun.numberOfGlyphs = numberOfIndices;
1003           mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
1004
1005           //Mark-up processor case
1006           if(mModel->mVisualModel->IsMarkupProcessorEnabled())
1007           {
1008             CopyUnderlinedFromLogicalToVisualModels(false);
1009           }
1010           break;
1011         }
1012         case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4:
1013         {
1014           // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together.
1015           ColorRun backgroundColorRun;
1016           backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
1017           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
1018           backgroundColorRun.color                           = BACKGROUND_SUB7;
1019           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
1020
1021           GlyphRun underlineRun;
1022           underlineRun.glyphIndex     = attrData.startIndex + numberOfCommit;
1023           underlineRun.numberOfGlyphs = numberOfIndices;
1024           mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
1025
1026           //Mark-up processor case
1027           if(mModel->mVisualModel->IsMarkupProcessorEnabled())
1028           {
1029             CopyUnderlinedFromLogicalToVisualModels(false);
1030           }
1031           break;
1032         }
1033         case Dali::InputMethodContext::PreeditStyle::NONE:
1034         default:
1035         {
1036           break;
1037         }
1038       }
1039     }
1040     attrs.Clear();
1041     updated = true;
1042   }
1043
1044   if(NO_OPERATION != (COLOR & operations))
1045   {
1046     // Set the color runs in glyphs.
1047     SetColorSegmentationInfo(mModel->mLogicalModel->mColorRuns,
1048                              mModel->mVisualModel->mCharactersToGlyph,
1049                              mModel->mVisualModel->mGlyphsPerCharacter,
1050                              startIndex,
1051                              mTextUpdateInfo.mStartGlyphIndex,
1052                              requestedNumberOfCharacters,
1053                              mModel->mVisualModel->mColors,
1054                              mModel->mVisualModel->mColorIndices);
1055
1056     // Set the background color runs in glyphs.
1057     SetColorSegmentationInfo(mModel->mLogicalModel->mBackgroundColorRuns,
1058                              mModel->mVisualModel->mCharactersToGlyph,
1059                              mModel->mVisualModel->mGlyphsPerCharacter,
1060                              startIndex,
1061                              mTextUpdateInfo.mStartGlyphIndex,
1062                              requestedNumberOfCharacters,
1063                              mModel->mVisualModel->mBackgroundColors,
1064                              mModel->mVisualModel->mBackgroundColorIndices);
1065
1066     updated = true;
1067   }
1068
1069   if((NO_OPERATION != (SHAPE_TEXT & operations)) &&
1070      !((nullptr != mEventData) &&
1071        mEventData->mPreEditFlag &&
1072        (0u != mModel->mVisualModel->mCharactersToGlyph.Count())))
1073   {
1074     //Mark-up processor case
1075     if(mModel->mVisualModel->IsMarkupProcessorEnabled())
1076     {
1077       CopyUnderlinedFromLogicalToVisualModels(true);
1078     }
1079
1080     updated = true;
1081   }
1082
1083   // The estimated number of lines. Used to avoid reallocations when layouting.
1084   mTextUpdateInfo.mEstimatedNumberOfLines = std::max(mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count());
1085
1086   // Set the previous number of characters for the next time the text is updated.
1087   mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters;
1088
1089   return updated;
1090 }
1091
1092 void Controller::Impl::RetrieveDefaultInputStyle(InputStyle& inputStyle)
1093 {
1094   // Sets the default text's color.
1095   inputStyle.textColor      = mTextColor;
1096   inputStyle.isDefaultColor = true;
1097
1098   inputStyle.familyName.clear();
1099   inputStyle.weight = TextAbstraction::FontWeight::NORMAL;
1100   inputStyle.width  = TextAbstraction::FontWidth::NORMAL;
1101   inputStyle.slant  = TextAbstraction::FontSlant::NORMAL;
1102   inputStyle.size   = 0.f;
1103
1104   inputStyle.lineSpacing = 0.f;
1105
1106   inputStyle.underlineProperties.clear();
1107   inputStyle.shadowProperties.clear();
1108   inputStyle.embossProperties.clear();
1109   inputStyle.outlineProperties.clear();
1110
1111   inputStyle.isFamilyDefined = false;
1112   inputStyle.isWeightDefined = false;
1113   inputStyle.isWidthDefined  = false;
1114   inputStyle.isSlantDefined  = false;
1115   inputStyle.isSizeDefined   = false;
1116
1117   inputStyle.isLineSpacingDefined = false;
1118
1119   inputStyle.isUnderlineDefined = false;
1120   inputStyle.isShadowDefined    = false;
1121   inputStyle.isEmbossDefined    = false;
1122   inputStyle.isOutlineDefined   = false;
1123
1124   // Sets the default font's family name, weight, width, slant and size.
1125   if(mFontDefaults)
1126   {
1127     if(mFontDefaults->familyDefined)
1128     {
1129       inputStyle.familyName      = mFontDefaults->mFontDescription.family;
1130       inputStyle.isFamilyDefined = true;
1131     }
1132
1133     if(mFontDefaults->weightDefined)
1134     {
1135       inputStyle.weight          = mFontDefaults->mFontDescription.weight;
1136       inputStyle.isWeightDefined = true;
1137     }
1138
1139     if(mFontDefaults->widthDefined)
1140     {
1141       inputStyle.width          = mFontDefaults->mFontDescription.width;
1142       inputStyle.isWidthDefined = true;
1143     }
1144
1145     if(mFontDefaults->slantDefined)
1146     {
1147       inputStyle.slant          = mFontDefaults->mFontDescription.slant;
1148       inputStyle.isSlantDefined = true;
1149     }
1150
1151     if(mFontDefaults->sizeDefined)
1152     {
1153       inputStyle.size          = mFontDefaults->mDefaultPointSize;
1154       inputStyle.isSizeDefined = true;
1155     }
1156   }
1157 }
1158
1159 float Controller::Impl::GetDefaultFontLineHeight()
1160 {
1161   FontId defaultFontId = 0u;
1162   if(nullptr == mFontDefaults)
1163   {
1164     TextAbstraction::FontDescription fontDescription;
1165     defaultFontId = mFontClient.GetFontId(fontDescription, TextAbstraction::FontClient::DEFAULT_POINT_SIZE * mFontSizeScale);
1166   }
1167   else
1168   {
1169     defaultFontId = mFontDefaults->GetFontId(mFontClient, mFontDefaults->mDefaultPointSize * mFontSizeScale);
1170   }
1171
1172   Text::FontMetrics fontMetrics;
1173   mMetrics->GetFontMetrics(defaultFontId, fontMetrics);
1174
1175   return (fontMetrics.ascender - fontMetrics.descender);
1176 }
1177
1178 void Controller::Impl::SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEnd)
1179 {
1180   if(nullptr == mEventData)
1181   {
1182     // Nothing to do if there is no text.
1183     return;
1184   }
1185
1186   if(mEventData->mSelectionEnabled && (pStart || pEnd))
1187   {
1188     uint32_t length = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
1189
1190     if(pStart)
1191     {
1192       mEventData->mLeftSelectionPosition = std::min(*pStart, length);
1193     }
1194     if(pEnd)
1195     {
1196       mEventData->mRightSelectionPosition = std::min(*pEnd, length);
1197     }
1198
1199     if(mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
1200     {
1201       ChangeState(EventData::EDITING);
1202       mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition;
1203       mEventData->mUpdateCursorPosition                                       = true;
1204     }
1205     else
1206     {
1207       ChangeState(EventData::SELECTING);
1208       mEventData->mUpdateHighlightBox           = true;
1209       mEventData->mUpdateLeftSelectionPosition  = true;
1210       mEventData->mUpdateRightSelectionPosition = true;
1211     }
1212   }
1213 }
1214
1215 CharacterIndex Controller::Impl::GetPrimaryCursorPosition() const
1216 {
1217   if(nullptr == mEventData)
1218   {
1219     return 0;
1220   }
1221   return mEventData->mPrimaryCursorPosition;
1222 }
1223
1224 bool Controller::Impl::SetPrimaryCursorPosition(CharacterIndex index)
1225 {
1226   if(nullptr == mEventData)
1227   {
1228     // Nothing to do if there is no text.
1229     return false;
1230   }
1231
1232   if(mEventData->mPrimaryCursorPosition == index)
1233   {
1234     // Nothing for same cursor position.
1235     return false;
1236   }
1237
1238   uint32_t length                    = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
1239   mEventData->mPrimaryCursorPosition = std::min(index, length);
1240   ChangeState(EventData::EDITING);
1241   mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
1242   mEventData->mUpdateCursorPosition                                        = true;
1243   ScrollTextToMatchCursor();
1244   return true;
1245 }
1246
1247 Uint32Pair Controller::Impl::GetTextSelectionRange() const
1248 {
1249   Uint32Pair range;
1250
1251   if(mEventData)
1252   {
1253     range.first  = mEventData->mLeftSelectionPosition;
1254     range.second = mEventData->mRightSelectionPosition;
1255   }
1256
1257   return range;
1258 }
1259
1260 bool Controller::Impl::IsEditable() const
1261 {
1262   return mEventData && mEventData->mEditingEnabled;
1263 }
1264
1265 void Controller::Impl::SetEditable(bool editable)
1266 {
1267   if(mEventData)
1268   {
1269     mEventData->mEditingEnabled = editable;
1270   }
1271 }
1272
1273 void Controller::Impl::RetrieveSelection(std::string& selectedText, bool deleteAfterRetrieval)
1274 {
1275   if(mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
1276   {
1277     // Nothing to select if handles are in the same place.
1278     selectedText.clear();
1279     return;
1280   }
1281
1282   const bool handlesCrossed = mEventData->mLeftSelectionPosition > mEventData->mRightSelectionPosition;
1283
1284   //Get start and end position of selection
1285   const CharacterIndex startOfSelectedText  = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
1286   const Length         lengthOfSelectedText = (handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition) - startOfSelectedText;
1287
1288   Vector<Character>& utf32Characters    = mModel->mLogicalModel->mText;
1289   const Length       numberOfCharacters = utf32Characters.Count();
1290
1291   // Validate the start and end selection points
1292   if((startOfSelectedText + lengthOfSelectedText) <= numberOfCharacters)
1293   {
1294     //Get text as a UTF8 string
1295     Utf32ToUtf8(&utf32Characters[startOfSelectedText], lengthOfSelectedText, selectedText);
1296
1297     if(deleteAfterRetrieval) // Only delete text if copied successfully
1298     {
1299       // Keep a copy of the current input style.
1300       InputStyle currentInputStyle;
1301       currentInputStyle.Copy(mEventData->mInputStyle);
1302
1303       // Set as input style the style of the first deleted character.
1304       mModel->mLogicalModel->RetrieveStyle(startOfSelectedText, mEventData->mInputStyle);
1305
1306       // Compare if the input style has changed.
1307       const bool hasInputStyleChanged = !currentInputStyle.Equal(mEventData->mInputStyle);
1308
1309       if(hasInputStyleChanged)
1310       {
1311         const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask(mEventData->mInputStyle);
1312         // Queue the input style changed signal.
1313         mEventData->mInputStyleChangedQueue.PushBack(styleChangedMask);
1314       }
1315
1316       mModel->mLogicalModel->UpdateTextStyleRuns(startOfSelectedText, -static_cast<int>(lengthOfSelectedText));
1317
1318       // Mark the paragraphs to be updated.
1319       if(Layout::Engine::SINGLE_LINE_BOX == mLayoutEngine.GetLayout())
1320       {
1321         mTextUpdateInfo.mCharacterIndex             = 0;
1322         mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
1323         mTextUpdateInfo.mNumberOfCharactersToAdd    = mTextUpdateInfo.mPreviousNumberOfCharacters - lengthOfSelectedText;
1324         mTextUpdateInfo.mClearAll                   = true;
1325       }
1326       else
1327       {
1328         mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
1329         mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
1330       }
1331
1332       // Delete text between handles
1333       Vector<Character>::Iterator first = utf32Characters.Begin() + startOfSelectedText;
1334       Vector<Character>::Iterator last  = first + lengthOfSelectedText;
1335       utf32Characters.Erase(first, last);
1336
1337       // Will show the cursor at the first character of the selection.
1338       mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
1339     }
1340     else
1341     {
1342       // Will show the cursor at the last character of the selection.
1343       mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition;
1344     }
1345
1346     mEventData->mDecoratorUpdated = true;
1347   }
1348 }
1349
1350 void Controller::Impl::SetSelection(int start, int end)
1351 {
1352   mEventData->mLeftSelectionPosition  = start;
1353   mEventData->mRightSelectionPosition = end;
1354   mEventData->mUpdateCursorPosition   = true;
1355 }
1356
1357 std::pair<int, int> Controller::Impl::GetSelectionIndexes() const
1358 {
1359   return {mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition};
1360 }
1361
1362 void Controller::Impl::ShowClipboard()
1363 {
1364   if(mClipboard)
1365   {
1366     mClipboard.ShowClipboard();
1367   }
1368 }
1369
1370 void Controller::Impl::HideClipboard()
1371 {
1372   if(mClipboard && mClipboardHideEnabled)
1373   {
1374     mClipboard.HideClipboard();
1375   }
1376 }
1377
1378 void Controller::Impl::SetClipboardHideEnable(bool enable)
1379 {
1380   mClipboardHideEnabled = enable;
1381 }
1382
1383 bool Controller::Impl::CopyStringToClipboard(const std::string& source)
1384 {
1385   //Send string to clipboard
1386   return (mClipboard && mClipboard.SetItem(source));
1387 }
1388
1389 void Controller::Impl::SendSelectionToClipboard(bool deleteAfterSending)
1390 {
1391   std::string selectedText;
1392   RetrieveSelection(selectedText, deleteAfterSending);
1393   CopyStringToClipboard(selectedText);
1394   ChangeState(EventData::EDITING);
1395 }
1396
1397 void Controller::Impl::RequestGetTextFromClipboard()
1398 {
1399   if(mClipboard)
1400   {
1401     mClipboard.RequestItem();
1402   }
1403 }
1404
1405 void Controller::Impl::RepositionSelectionHandles()
1406 {
1407   SelectionHandleController::Reposition(*this);
1408 }
1409 void Controller::Impl::RepositionSelectionHandles(float visualX, float visualY, Controller::NoTextTap::Action action)
1410 {
1411   SelectionHandleController::Reposition(*this, visualX, visualY, action);
1412 }
1413
1414 void Controller::Impl::SetPopupButtons()
1415 {
1416   /**
1417    *  Sets the Popup buttons to be shown depending on State.
1418    *
1419    *  If SELECTING :  CUT & COPY + ( PASTE & CLIPBOARD if content available to paste )
1420    *
1421    *  If EDITING_WITH_POPUP : SELECT & SELECT_ALL
1422    */
1423
1424   bool                        isEditable    = IsEditable();
1425   TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::NONE;
1426
1427   if(EventData::SELECTING == mEventData->mState)
1428   {
1429     buttonsToShow = TextSelectionPopup::Buttons(TextSelectionPopup::COPY);
1430     if(isEditable)
1431     {
1432       buttonsToShow = TextSelectionPopup::Buttons(buttonsToShow | TextSelectionPopup::CUT);
1433     }
1434
1435     if(!IsClipboardEmpty())
1436     {
1437       if(isEditable)
1438       {
1439         buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
1440       }
1441       buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
1442     }
1443
1444     if(!mEventData->mAllTextSelected)
1445     {
1446       buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::SELECT_ALL));
1447     }
1448   }
1449   else if(EventData::EDITING_WITH_POPUP == mEventData->mState)
1450   {
1451     if(mModel->mLogicalModel->mText.Count() && !IsShowingPlaceholderText())
1452     {
1453       buttonsToShow = TextSelectionPopup::Buttons(TextSelectionPopup::SELECT | TextSelectionPopup::SELECT_ALL);
1454     }
1455
1456     if(!IsClipboardEmpty())
1457     {
1458       if(isEditable)
1459       {
1460         buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
1461       }
1462       buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
1463     }
1464   }
1465   else if(EventData::EDITING_WITH_PASTE_POPUP == mEventData->mState)
1466   {
1467     if(!IsClipboardEmpty())
1468     {
1469       if(isEditable)
1470       {
1471         buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
1472       }
1473       buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
1474     }
1475   }
1476
1477   mEventData->mDecorator->SetEnabledPopupButtons(buttonsToShow);
1478 }
1479
1480 void Controller::Impl::ChangeState(EventData::State newState)
1481 {
1482   if(nullptr == mEventData)
1483   {
1484     // Nothing to do if there is no text input.
1485     return;
1486   }
1487
1488   DALI_LOG_INFO(gLogFilter, Debug::General, "ChangeState state:%d  newstate:%d\n", mEventData->mState, newState);
1489
1490   if(mEventData->mState != newState)
1491   {
1492     mEventData->mPreviousState = mEventData->mState;
1493     mEventData->mState         = newState;
1494
1495     switch(mEventData->mState)
1496     {
1497       case EventData::INACTIVE:
1498       {
1499         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
1500         mEventData->mDecorator->StopCursorBlink();
1501         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1502         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1503         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1504         mEventData->mDecorator->SetHighlightActive(false);
1505         mEventData->mDecorator->SetPopupActive(false);
1506         mEventData->mDecoratorUpdated = true;
1507         break;
1508       }
1509       case EventData::INTERRUPTED:
1510       {
1511         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1512         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1513         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1514         mEventData->mDecorator->SetHighlightActive(false);
1515         mEventData->mDecorator->SetPopupActive(false);
1516         mEventData->mDecoratorUpdated = true;
1517         break;
1518       }
1519       case EventData::SELECTING:
1520       {
1521         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
1522         mEventData->mDecorator->StopCursorBlink();
1523         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1524         if(mEventData->mGrabHandleEnabled)
1525         {
1526           mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
1527           mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
1528         }
1529         mEventData->mDecorator->SetHighlightActive(true);
1530         if(mEventData->mGrabHandlePopupEnabled)
1531         {
1532           SetPopupButtons();
1533           mEventData->mDecorator->SetPopupActive(true);
1534         }
1535         mEventData->mDecoratorUpdated = true;
1536         break;
1537       }
1538       case EventData::EDITING:
1539       {
1540         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1541         if(mEventData->mCursorBlinkEnabled)
1542         {
1543           mEventData->mDecorator->StartCursorBlink();
1544         }
1545         // Grab handle is not shown until a tap is received whilst EDITING
1546         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1547         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1548         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1549         mEventData->mDecorator->SetHighlightActive(false);
1550         if(mEventData->mGrabHandlePopupEnabled)
1551         {
1552           mEventData->mDecorator->SetPopupActive(false);
1553         }
1554         mEventData->mDecoratorUpdated = true;
1555         break;
1556       }
1557       case EventData::EDITING_WITH_POPUP:
1558       {
1559         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_POPUP \n", newState);
1560
1561         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1562         if(mEventData->mCursorBlinkEnabled)
1563         {
1564           mEventData->mDecorator->StartCursorBlink();
1565         }
1566         if(mEventData->mSelectionEnabled)
1567         {
1568           mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1569           mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1570           mEventData->mDecorator->SetHighlightActive(false);
1571         }
1572         else if(mEventData->mGrabHandleEnabled)
1573         {
1574           mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
1575         }
1576         if(mEventData->mGrabHandlePopupEnabled)
1577         {
1578           SetPopupButtons();
1579           mEventData->mDecorator->SetPopupActive(true);
1580         }
1581         mEventData->mDecoratorUpdated = true;
1582         break;
1583       }
1584       case EventData::EDITING_WITH_GRAB_HANDLE:
1585       {
1586         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_GRAB_HANDLE \n", newState);
1587
1588         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1589         if(mEventData->mCursorBlinkEnabled)
1590         {
1591           mEventData->mDecorator->StartCursorBlink();
1592         }
1593         // Grab handle is not shown until a tap is received whilst EDITING
1594         if(mEventData->mGrabHandleEnabled)
1595         {
1596           mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
1597         }
1598         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1599         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1600         mEventData->mDecorator->SetHighlightActive(false);
1601         if(mEventData->mGrabHandlePopupEnabled)
1602         {
1603           mEventData->mDecorator->SetPopupActive(false);
1604         }
1605         mEventData->mDecoratorUpdated = true;
1606         break;
1607       }
1608       case EventData::SELECTION_HANDLE_PANNING:
1609       {
1610         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
1611         mEventData->mDecorator->StopCursorBlink();
1612         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1613         if(mEventData->mGrabHandleEnabled)
1614         {
1615           mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
1616           mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
1617         }
1618         mEventData->mDecorator->SetHighlightActive(true);
1619         if(mEventData->mGrabHandlePopupEnabled)
1620         {
1621           mEventData->mDecorator->SetPopupActive(false);
1622         }
1623         mEventData->mDecoratorUpdated = true;
1624         break;
1625       }
1626       case EventData::GRAB_HANDLE_PANNING:
1627       {
1628         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "GRAB_HANDLE_PANNING \n", newState);
1629
1630         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1631         if(mEventData->mCursorBlinkEnabled)
1632         {
1633           mEventData->mDecorator->StartCursorBlink();
1634         }
1635         if(mEventData->mGrabHandleEnabled)
1636         {
1637           mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
1638         }
1639         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1640         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1641         mEventData->mDecorator->SetHighlightActive(false);
1642         if(mEventData->mGrabHandlePopupEnabled)
1643         {
1644           mEventData->mDecorator->SetPopupActive(false);
1645         }
1646         mEventData->mDecoratorUpdated = true;
1647         break;
1648       }
1649       case EventData::EDITING_WITH_PASTE_POPUP:
1650       {
1651         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_PASTE_POPUP \n", newState);
1652
1653         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1654         if(mEventData->mCursorBlinkEnabled)
1655         {
1656           mEventData->mDecorator->StartCursorBlink();
1657         }
1658
1659         if(mEventData->mGrabHandleEnabled)
1660         {
1661           mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
1662         }
1663         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1664         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1665         mEventData->mDecorator->SetHighlightActive(false);
1666
1667         if(mEventData->mGrabHandlePopupEnabled)
1668         {
1669           SetPopupButtons();
1670           mEventData->mDecorator->SetPopupActive(true);
1671         }
1672         mEventData->mDecoratorUpdated = true;
1673         break;
1674       }
1675       case EventData::TEXT_PANNING:
1676       {
1677         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
1678         mEventData->mDecorator->StopCursorBlink();
1679         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1680         if(mEventData->mDecorator->IsHandleActive(LEFT_SELECTION_HANDLE) ||
1681            mEventData->mDecorator->IsHandleActive(RIGHT_SELECTION_HANDLE))
1682         {
1683           mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1684           mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1685           mEventData->mDecorator->SetHighlightActive(true);
1686         }
1687
1688         if(mEventData->mGrabHandlePopupEnabled)
1689         {
1690           mEventData->mDecorator->SetPopupActive(false);
1691         }
1692
1693         mEventData->mDecoratorUpdated = true;
1694         break;
1695       }
1696     }
1697   }
1698 }
1699
1700 void Controller::Impl::GetCursorPosition(CharacterIndex logical,
1701                                          CursorInfo&    cursorInfo)
1702 {
1703   if(!IsShowingRealText())
1704   {
1705     // Do not want to use the place-holder text to set the cursor position.
1706
1707     // Use the line's height of the font's family set to set the cursor's size.
1708     // If there is no font's family set, use the default font.
1709     // Use the current alignment to place the cursor at the beginning, center or end of the box.
1710
1711     cursorInfo.lineOffset          = 0.f;
1712     cursorInfo.lineHeight          = GetDefaultFontLineHeight();
1713     cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
1714
1715     bool isRTL = false;
1716     if(mModel->mMatchSystemLanguageDirection)
1717     {
1718       isRTL = mLayoutDirection == LayoutDirection::RIGHT_TO_LEFT;
1719     }
1720
1721     switch(mModel->mHorizontalAlignment)
1722     {
1723       case Text::HorizontalAlignment::BEGIN:
1724       {
1725         if(isRTL)
1726         {
1727           cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
1728         }
1729         else
1730         {
1731           cursorInfo.primaryPosition.x = 0.f;
1732         }
1733         break;
1734       }
1735       case Text::HorizontalAlignment::CENTER:
1736       {
1737         cursorInfo.primaryPosition.x = floorf(0.5f * mModel->mVisualModel->mControlSize.width);
1738         break;
1739       }
1740       case Text::HorizontalAlignment::END:
1741       {
1742         if(isRTL)
1743         {
1744           cursorInfo.primaryPosition.x = 0.f;
1745         }
1746         else
1747         {
1748           cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
1749         }
1750         break;
1751       }
1752     }
1753
1754     // Nothing else to do.
1755     return;
1756   }
1757
1758   const bool                  isMultiLine = (Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout());
1759   GetCursorPositionParameters parameters;
1760   parameters.visualModel  = mModel->mVisualModel;
1761   parameters.logicalModel = mModel->mLogicalModel;
1762   parameters.metrics      = mMetrics;
1763   parameters.logical      = logical;
1764   parameters.isMultiline  = isMultiLine;
1765
1766   Text::GetCursorPosition(parameters,
1767                           cursorInfo);
1768
1769   // Adds Outline offset.
1770   const float outlineWidth = static_cast<float>(mModel->GetOutlineWidth());
1771   cursorInfo.primaryPosition.x += outlineWidth;
1772   cursorInfo.primaryPosition.y += outlineWidth;
1773   cursorInfo.secondaryPosition.x += outlineWidth;
1774   cursorInfo.secondaryPosition.y += outlineWidth;
1775
1776   if(isMultiLine)
1777   {
1778     // If the text is editable and multi-line, the cursor position after a white space shouldn't exceed the boundaries of the text control.
1779
1780     // Note the white spaces laid-out at the end of the line might exceed the boundaries of the control.
1781     // The reason is a wrapped line must not start with a white space so they are laid-out at the end of the line.
1782
1783     if(0.f > cursorInfo.primaryPosition.x)
1784     {
1785       cursorInfo.primaryPosition.x = 0.f;
1786     }
1787
1788     const float edgeWidth = mModel->mVisualModel->mControlSize.width - static_cast<float>(mEventData->mDecorator->GetCursorWidth());
1789     if(cursorInfo.primaryPosition.x > edgeWidth)
1790     {
1791       cursorInfo.primaryPosition.x = edgeWidth;
1792     }
1793   }
1794 }
1795
1796 CharacterIndex Controller::Impl::CalculateNewCursorIndex(CharacterIndex index) const
1797 {
1798   if(nullptr == mEventData)
1799   {
1800     // Nothing to do if there is no text input.
1801     return 0u;
1802   }
1803
1804   CharacterIndex cursorIndex = mEventData->mPrimaryCursorPosition;
1805
1806   const GlyphIndex* const charactersToGlyphBuffer  = mModel->mVisualModel->mCharactersToGlyph.Begin();
1807   const Length* const     charactersPerGlyphBuffer = mModel->mVisualModel->mCharactersPerGlyph.Begin();
1808
1809   GlyphIndex glyphIndex         = *(charactersToGlyphBuffer + index);
1810   Length     numberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
1811
1812   if(numberOfCharacters > 1u)
1813   {
1814     const Script script = mModel->mLogicalModel->GetScript(index);
1815     if(HasLigatureMustBreak(script))
1816     {
1817       // Prevents to jump the whole Latin ligatures like fi, ff, or Arabic ï»», ...
1818       numberOfCharacters = 1u;
1819     }
1820   }
1821   else
1822   {
1823     while(0u == numberOfCharacters)
1824     {
1825       ++glyphIndex;
1826       numberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
1827     }
1828   }
1829
1830   if(index < mEventData->mPrimaryCursorPosition)
1831   {
1832     cursorIndex -= numberOfCharacters;
1833   }
1834   else
1835   {
1836     cursorIndex += numberOfCharacters;
1837   }
1838
1839   // Will update the cursor hook position.
1840   mEventData->mUpdateCursorHookPosition = true;
1841
1842   return cursorIndex;
1843 }
1844
1845 void Controller::Impl::UpdateCursorPosition(const CursorInfo& cursorInfo)
1846 {
1847   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::UpdateCursorPosition %p\n", this);
1848   if(nullptr == mEventData)
1849   {
1850     // Nothing to do if there is no text input.
1851     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition no event data\n");
1852     return;
1853   }
1854
1855   const Vector2 cursorPosition = cursorInfo.primaryPosition + mModel->mScrollPosition;
1856
1857   mEventData->mDecorator->SetGlyphOffset(PRIMARY_CURSOR, cursorInfo.glyphOffset);
1858
1859   // Sets the cursor position.
1860   mEventData->mDecorator->SetPosition(PRIMARY_CURSOR,
1861                                       cursorPosition.x,
1862                                       cursorPosition.y,
1863                                       cursorInfo.primaryCursorHeight,
1864                                       cursorInfo.lineHeight);
1865   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Primary cursor position: %f,%f\n", cursorPosition.x, cursorPosition.y);
1866
1867   if(mEventData->mUpdateGrabHandlePosition)
1868   {
1869     // Sets the grab handle position.
1870     mEventData->mDecorator->SetPosition(GRAB_HANDLE,
1871                                         cursorPosition.x,
1872                                         cursorInfo.lineOffset + mModel->mScrollPosition.y,
1873                                         cursorInfo.lineHeight);
1874   }
1875
1876   if(cursorInfo.isSecondaryCursor)
1877   {
1878     mEventData->mDecorator->SetPosition(SECONDARY_CURSOR,
1879                                         cursorInfo.secondaryPosition.x + mModel->mScrollPosition.x,
1880                                         cursorInfo.secondaryPosition.y + mModel->mScrollPosition.y,
1881                                         cursorInfo.secondaryCursorHeight,
1882                                         cursorInfo.lineHeight);
1883     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + mModel->mScrollPosition.x, cursorInfo.secondaryPosition.y + mModel->mScrollPosition.y);
1884   }
1885
1886   // Set which cursors are active according the state.
1887   if(EventData::IsEditingState(mEventData->mState) || (EventData::GRAB_HANDLE_PANNING == mEventData->mState))
1888   {
1889     if(cursorInfo.isSecondaryCursor)
1890     {
1891       mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_BOTH);
1892     }
1893     else
1894     {
1895       mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1896     }
1897   }
1898   else
1899   {
1900     mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
1901   }
1902
1903   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition\n");
1904 }
1905
1906 void Controller::Impl::UpdateSelectionHandle(HandleType        handleType,
1907                                              const CursorInfo& cursorInfo)
1908 {
1909   SelectionHandleController::Update(*this, handleType, cursorInfo);
1910 }
1911
1912 void Controller::Impl::ClampHorizontalScroll(const Vector2& layoutSize)
1913 {
1914   // Clamp between -space & -alignment offset.
1915
1916   if(layoutSize.width > mModel->mVisualModel->mControlSize.width)
1917   {
1918     const float space         = (layoutSize.width - mModel->mVisualModel->mControlSize.width) + mModel->mAlignmentOffset;
1919     mModel->mScrollPosition.x = (mModel->mScrollPosition.x < -space) ? -space : mModel->mScrollPosition.x;
1920     mModel->mScrollPosition.x = (mModel->mScrollPosition.x > -mModel->mAlignmentOffset) ? -mModel->mAlignmentOffset : mModel->mScrollPosition.x;
1921
1922     mEventData->mDecoratorUpdated = true;
1923   }
1924   else
1925   {
1926     mModel->mScrollPosition.x = 0.f;
1927   }
1928 }
1929
1930 void Controller::Impl::ClampVerticalScroll(const Vector2& layoutSize)
1931 {
1932   if(Layout::Engine::SINGLE_LINE_BOX == mLayoutEngine.GetLayout())
1933   {
1934     // Nothing to do if the text is single line.
1935     return;
1936   }
1937
1938   // Clamp between -space & 0.
1939   if(layoutSize.height > mModel->mVisualModel->mControlSize.height)
1940   {
1941     const float space         = (layoutSize.height - mModel->mVisualModel->mControlSize.height);
1942     mModel->mScrollPosition.y = (mModel->mScrollPosition.y < -space) ? -space : mModel->mScrollPosition.y;
1943     mModel->mScrollPosition.y = (mModel->mScrollPosition.y > 0.f) ? 0.f : mModel->mScrollPosition.y;
1944
1945     mEventData->mDecoratorUpdated = true;
1946   }
1947   else
1948   {
1949     mModel->mScrollPosition.y = 0.f;
1950   }
1951 }
1952
1953 void Controller::Impl::ScrollToMakePositionVisible(const Vector2& position, float lineHeight)
1954 {
1955   const float cursorWidth = mEventData->mDecorator ? static_cast<float>(mEventData->mDecorator->GetCursorWidth()) : 0.f;
1956
1957   // position is in actor's coords.
1958   const float positionEndX = position.x + cursorWidth;
1959   const float positionEndY = position.y + lineHeight;
1960
1961   // Transform the position to decorator coords.
1962   const float decoratorPositionBeginX = position.x + mModel->mScrollPosition.x;
1963   const float decoratorPositionEndX   = positionEndX + mModel->mScrollPosition.x;
1964
1965   const float decoratorPositionBeginY = position.y + mModel->mScrollPosition.y;
1966   const float decoratorPositionEndY   = positionEndY + mModel->mScrollPosition.y;
1967
1968   if(decoratorPositionBeginX < 0.f)
1969   {
1970     mModel->mScrollPosition.x = -position.x;
1971   }
1972   else if(decoratorPositionEndX > mModel->mVisualModel->mControlSize.width)
1973   {
1974     mModel->mScrollPosition.x = mModel->mVisualModel->mControlSize.width - positionEndX;
1975   }
1976
1977   if(Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout())
1978   {
1979     if(decoratorPositionBeginY < 0.f)
1980     {
1981       mModel->mScrollPosition.y = -position.y;
1982     }
1983     else if(decoratorPositionEndY > mModel->mVisualModel->mControlSize.height)
1984     {
1985       mModel->mScrollPosition.y = mModel->mVisualModel->mControlSize.height - positionEndY;
1986     }
1987   }
1988 }
1989
1990 void Controller::Impl::ScrollTextToMatchCursor(const CursorInfo& cursorInfo)
1991 {
1992   // Get the current cursor position in decorator coords.
1993   const Vector2& currentCursorPosition = mEventData->mDecorator->GetPosition(PRIMARY_CURSOR);
1994
1995   const LineIndex lineIndex = mModel->mVisualModel->GetLineOfCharacter(mEventData->mPrimaryCursorPosition);
1996
1997   // Calculate the offset to match the cursor position before the character was deleted.
1998   mModel->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x;
1999
2000   //If text control has more than two lines and current line index is not last, calculate scrollpositionY
2001   if(mModel->mVisualModel->mLines.Count() > 1u && lineIndex != mModel->mVisualModel->mLines.Count() - 1u)
2002   {
2003     const float currentCursorGlyphOffset = mEventData->mDecorator->GetGlyphOffset(PRIMARY_CURSOR);
2004     mModel->mScrollPosition.y            = currentCursorPosition.y - cursorInfo.lineOffset - currentCursorGlyphOffset;
2005   }
2006
2007   ClampHorizontalScroll(mModel->mVisualModel->GetLayoutSize());
2008   ClampVerticalScroll(mModel->mVisualModel->GetLayoutSize());
2009
2010   // Makes the new cursor position visible if needed.
2011   ScrollToMakePositionVisible(cursorInfo.primaryPosition, cursorInfo.lineHeight);
2012 }
2013
2014 void Controller::Impl::ScrollTextToMatchCursor()
2015 {
2016   CursorInfo cursorInfo;
2017   GetCursorPosition(mEventData->mPrimaryCursorPosition, cursorInfo);
2018   ScrollTextToMatchCursor(cursorInfo);
2019 }
2020
2021 void Controller::Impl::RequestRelayout()
2022 {
2023   if(nullptr != mControlInterface)
2024   {
2025     mControlInterface->RequestTextRelayout();
2026   }
2027 }
2028
2029 Actor Controller::Impl::CreateBackgroundActor()
2030 {
2031   // NOTE: Currently we only support background color for left-to-right text.
2032
2033   Actor actor;
2034
2035   Length numberOfGlyphs = mView.GetNumberOfGlyphs();
2036   if(numberOfGlyphs > 0u)
2037   {
2038     Vector<GlyphInfo> glyphs;
2039     glyphs.Resize(numberOfGlyphs);
2040
2041     Vector<Vector2> positions;
2042     positions.Resize(numberOfGlyphs);
2043
2044     // Get the line where the glyphs are laid-out.
2045     const LineRun* lineRun         = mModel->mVisualModel->mLines.Begin();
2046     float          alignmentOffset = lineRun->alignmentOffset;
2047     numberOfGlyphs                 = mView.GetGlyphs(glyphs.Begin(),
2048                                      positions.Begin(),
2049                                      alignmentOffset,
2050                                      0u,
2051                                      numberOfGlyphs);
2052
2053     glyphs.Resize(numberOfGlyphs);
2054     positions.Resize(numberOfGlyphs);
2055
2056     const GlyphInfo* const glyphsBuffer    = glyphs.Begin();
2057     const Vector2* const   positionsBuffer = positions.Begin();
2058
2059     BackgroundMesh mesh;
2060     mesh.mVertices.Reserve(4u * glyphs.Size());
2061     mesh.mIndices.Reserve(6u * glyphs.Size());
2062
2063     const Vector2 textSize = mView.GetLayoutSize();
2064
2065     const float offsetX = textSize.width * 0.5f;
2066     const float offsetY = textSize.height * 0.5f;
2067
2068     const Vector4* const    backgroundColorsBuffer       = mView.GetBackgroundColors();
2069     const ColorIndex* const backgroundColorIndicesBuffer = mView.GetBackgroundColorIndices();
2070     const Vector4&          defaultBackgroundColor       = mModel->mVisualModel->IsBackgroundEnabled() ? mModel->mVisualModel->GetBackgroundColor() : Color::TRANSPARENT;
2071
2072     Vector4   quad;
2073     uint32_t  numberOfQuads = 0u;
2074     Length    yLineOffset   = 0;
2075     Length    prevLineIndex = 0;
2076     LineIndex lineIndex;
2077     Length    numberOfLines;
2078
2079     for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i)
2080     {
2081       const GlyphInfo& glyph = *(glyphsBuffer + i);
2082
2083       // Get the background color of the character.
2084       // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT)
2085       const ColorIndex backgroundColorIndex = (nullptr == backgroundColorsBuffer) ? 0u : *(backgroundColorIndicesBuffer + i);
2086       const Vector4&   backgroundColor      = (0u == backgroundColorIndex) ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u);
2087
2088       mModel->mVisualModel->GetNumberOfLines(i, 1, lineIndex, numberOfLines);
2089       Length lineHeight = lineRun[lineIndex].ascender + -(lineRun[lineIndex].descender) + lineRun[lineIndex].lineSpacing;
2090
2091       if(lineIndex != prevLineIndex)
2092       {
2093         yLineOffset += lineHeight;
2094       }
2095
2096       // Only create quads for glyphs with a background color
2097       if(backgroundColor != Color::TRANSPARENT)
2098       {
2099         const Vector2 position = *(positionsBuffer + i);
2100
2101         if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text
2102         {
2103           quad.x = position.x;
2104           quad.y = yLineOffset;
2105           quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
2106           quad.w = lineHeight;
2107         }
2108         else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line
2109         {
2110           quad.x = position.x;
2111           quad.y = yLineOffset;
2112           quad.z = quad.x - glyph.xBearing + glyph.advance;
2113           quad.w = quad.y + lineHeight;
2114         }
2115         else if(i == glyphSize - 1u) // The last glyph in the whole text
2116         {
2117           quad.x = position.x - glyph.xBearing;
2118           quad.y = yLineOffset;
2119           quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
2120           quad.w = quad.y + lineHeight;
2121         }
2122         else // The glyph in the middle of the text
2123         {
2124           quad.x = position.x - glyph.xBearing;
2125           quad.y = yLineOffset;
2126           quad.z = quad.x + glyph.advance;
2127           quad.w = quad.y + lineHeight;
2128         }
2129
2130         BackgroundVertex vertex;
2131
2132         // Top left
2133         vertex.mPosition.x = quad.x - offsetX;
2134         vertex.mPosition.y = quad.y - offsetY;
2135         vertex.mColor      = backgroundColor;
2136         mesh.mVertices.PushBack(vertex);
2137
2138         // Top right
2139         vertex.mPosition.x = quad.z - offsetX;
2140         vertex.mPosition.y = quad.y - offsetY;
2141         vertex.mColor      = backgroundColor;
2142         mesh.mVertices.PushBack(vertex);
2143
2144         // Bottom left
2145         vertex.mPosition.x = quad.x - offsetX;
2146         vertex.mPosition.y = quad.w - offsetY;
2147         vertex.mColor      = backgroundColor;
2148         mesh.mVertices.PushBack(vertex);
2149
2150         // Bottom right
2151         vertex.mPosition.x = quad.z - offsetX;
2152         vertex.mPosition.y = quad.w - offsetY;
2153         vertex.mColor      = backgroundColor;
2154         mesh.mVertices.PushBack(vertex);
2155
2156         // Six indices in counter clockwise winding
2157         mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
2158         mesh.mIndices.PushBack(0u + 4 * numberOfQuads);
2159         mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
2160         mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
2161         mesh.mIndices.PushBack(3u + 4 * numberOfQuads);
2162         mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
2163
2164         numberOfQuads++;
2165       }
2166
2167       if(lineIndex != prevLineIndex)
2168       {
2169         prevLineIndex = lineIndex;
2170       }
2171     }
2172
2173     // Only create the background actor if there are glyphs with background color
2174     if(mesh.mVertices.Count() > 0u)
2175     {
2176       Property::Map quadVertexFormat;
2177       quadVertexFormat["aPosition"] = Property::VECTOR2;
2178       quadVertexFormat["aColor"]    = Property::VECTOR4;
2179
2180       VertexBuffer quadVertices = VertexBuffer::New(quadVertexFormat);
2181       quadVertices.SetData(&mesh.mVertices[0], mesh.mVertices.Size());
2182
2183       Geometry quadGeometry = Geometry::New();
2184       quadGeometry.AddVertexBuffer(quadVertices);
2185       quadGeometry.SetIndexBuffer(&mesh.mIndices[0], mesh.mIndices.Size());
2186
2187       if(!mShaderBackground)
2188       {
2189         mShaderBackground = Shader::New(SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_VERT, SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_FRAG);
2190       }
2191
2192       Dali::Renderer renderer = Dali::Renderer::New(quadGeometry, mShaderBackground);
2193       renderer.SetProperty(Dali::Renderer::Property::BLEND_MODE, BlendMode::ON);
2194       renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT);
2195
2196       actor = Actor::New();
2197       actor.SetProperty(Dali::Actor::Property::NAME, "TextBackgroundColorActor");
2198       actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
2199       actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
2200       actor.SetProperty(Actor::Property::SIZE, textSize);
2201       actor.SetProperty(Actor::Property::COLOR_MODE, USE_OWN_MULTIPLY_PARENT_COLOR);
2202       actor.AddRenderer(renderer);
2203     }
2204   }
2205
2206   return actor;
2207 }
2208
2209 void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns)
2210 {
2211   //Underlined character runs for markup-processor
2212   const Vector<UnderlinedCharacterRun>& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns;
2213   const Vector<GlyphIndex>&             charactersToGlyph       = mModel->mVisualModel->mCharactersToGlyph;
2214   const Vector<Length>&                 glyphsPerCharacter      = mModel->mVisualModel->mGlyphsPerCharacter;
2215
2216   if(shouldClearPreUnderlineRuns)
2217   {
2218     mModel->mVisualModel->mUnderlineRuns.Clear();
2219   }
2220
2221   for(Vector<UnderlinedCharacterRun>::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it)
2222   {
2223     CharacterIndex characterIndex     = it->characterRun.characterIndex;
2224     Length         numberOfCharacters = it->characterRun.numberOfCharacters;
2225     for(Length index = 0u; index < numberOfCharacters; index++)
2226     {
2227       GlyphRun underlineGlyphRun;
2228       underlineGlyphRun.glyphIndex     = charactersToGlyph[characterIndex + index];
2229       underlineGlyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index];
2230       mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
2231     }
2232   }
2233 }
2234
2235 } // namespace Text
2236
2237 } // namespace Toolkit
2238
2239 } // namespace Dali