a513d7064081a34958b53b78d42d1d4144f0aef1
[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
926           mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
927           break;
928         }
929         case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
930         {
931           ColorRun backgroundColorRun;
932           backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
933           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
934           backgroundColorRun.color                           = LIGHT_BLUE;
935           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
936           break;
937         }
938         case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
939         {
940           // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together.
941           ColorRun backgroundColorRun;
942           backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
943           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
944           backgroundColorRun.color                           = BACKGROUND_SUB4;
945           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
946
947           GlyphRun underlineRun;
948           underlineRun.glyphIndex     = attrData.startIndex + numberOfCommit;
949           underlineRun.numberOfGlyphs = numberOfIndices;
950           mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
951
952           //Mark-up processor case
953           if(mModel->mVisualModel->IsMarkupProcessorEnabled())
954           {
955             CopyUnderlinedFromLogicalToVisualModels(false);
956           }
957           break;
958         }
959         case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2:
960         {
961           // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together.
962           ColorRun backgroundColorRun;
963           backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
964           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
965           backgroundColorRun.color                           = BACKGROUND_SUB5;
966           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
967
968           GlyphRun underlineRun;
969           underlineRun.glyphIndex     = attrData.startIndex + numberOfCommit;
970           underlineRun.numberOfGlyphs = numberOfIndices;
971           mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
972
973           //Mark-up processor case
974           if(mModel->mVisualModel->IsMarkupProcessorEnabled())
975           {
976             CopyUnderlinedFromLogicalToVisualModels(false);
977           }
978           break;
979         }
980         case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3:
981         {
982           // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together.
983           ColorRun backgroundColorRun;
984           backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
985           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
986           backgroundColorRun.color                           = BACKGROUND_SUB6;
987           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
988
989           GlyphRun underlineRun;
990           underlineRun.glyphIndex     = attrData.startIndex + numberOfCommit;
991           underlineRun.numberOfGlyphs = numberOfIndices;
992           mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
993
994           //Mark-up processor case
995           if(mModel->mVisualModel->IsMarkupProcessorEnabled())
996           {
997             CopyUnderlinedFromLogicalToVisualModels(false);
998           }
999           break;
1000         }
1001         case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4:
1002         {
1003           // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together.
1004           ColorRun backgroundColorRun;
1005           backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
1006           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
1007           backgroundColorRun.color                           = BACKGROUND_SUB7;
1008           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
1009
1010           GlyphRun underlineRun;
1011           underlineRun.glyphIndex     = attrData.startIndex + numberOfCommit;
1012           underlineRun.numberOfGlyphs = numberOfIndices;
1013           mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
1014
1015           //Mark-up processor case
1016           if(mModel->mVisualModel->IsMarkupProcessorEnabled())
1017           {
1018             CopyUnderlinedFromLogicalToVisualModels(false);
1019           }
1020           break;
1021         }
1022         case Dali::InputMethodContext::PreeditStyle::NONE:
1023         default:
1024         {
1025           break;
1026         }
1027       }
1028     }
1029     attrs.Clear();
1030     updated = true;
1031   }
1032
1033   if(NO_OPERATION != (COLOR & operations))
1034   {
1035     // Set the color runs in glyphs.
1036     SetColorSegmentationInfo(mModel->mLogicalModel->mColorRuns,
1037                              mModel->mVisualModel->mCharactersToGlyph,
1038                              mModel->mVisualModel->mGlyphsPerCharacter,
1039                              startIndex,
1040                              mTextUpdateInfo.mStartGlyphIndex,
1041                              requestedNumberOfCharacters,
1042                              mModel->mVisualModel->mColors,
1043                              mModel->mVisualModel->mColorIndices);
1044
1045     // Set the background color runs in glyphs.
1046     SetColorSegmentationInfo(mModel->mLogicalModel->mBackgroundColorRuns,
1047                              mModel->mVisualModel->mCharactersToGlyph,
1048                              mModel->mVisualModel->mGlyphsPerCharacter,
1049                              startIndex,
1050                              mTextUpdateInfo.mStartGlyphIndex,
1051                              requestedNumberOfCharacters,
1052                              mModel->mVisualModel->mBackgroundColors,
1053                              mModel->mVisualModel->mBackgroundColorIndices);
1054
1055     updated = true;
1056   }
1057
1058   if((NO_OPERATION != (SHAPE_TEXT & operations)) &&
1059      !((nullptr != mEventData) &&
1060        mEventData->mPreEditFlag &&
1061        (0u != mModel->mVisualModel->mCharactersToGlyph.Count())))
1062   {
1063     //Mark-up processor case
1064     if(mModel->mVisualModel->IsMarkupProcessorEnabled())
1065     {
1066       CopyUnderlinedFromLogicalToVisualModels(true);
1067     }
1068
1069     updated = true;
1070   }
1071
1072   // The estimated number of lines. Used to avoid reallocations when layouting.
1073   mTextUpdateInfo.mEstimatedNumberOfLines = std::max(mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count());
1074
1075   // Set the previous number of characters for the next time the text is updated.
1076   mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters;
1077
1078   return updated;
1079 }
1080
1081 void Controller::Impl::RetrieveDefaultInputStyle(InputStyle& inputStyle)
1082 {
1083   // Sets the default text's color.
1084   inputStyle.textColor      = mTextColor;
1085   inputStyle.isDefaultColor = true;
1086
1087   inputStyle.familyName.clear();
1088   inputStyle.weight = TextAbstraction::FontWeight::NORMAL;
1089   inputStyle.width  = TextAbstraction::FontWidth::NORMAL;
1090   inputStyle.slant  = TextAbstraction::FontSlant::NORMAL;
1091   inputStyle.size   = 0.f;
1092
1093   inputStyle.lineSpacing = 0.f;
1094
1095   inputStyle.underlineProperties.clear();
1096   inputStyle.shadowProperties.clear();
1097   inputStyle.embossProperties.clear();
1098   inputStyle.outlineProperties.clear();
1099
1100   inputStyle.isFamilyDefined = false;
1101   inputStyle.isWeightDefined = false;
1102   inputStyle.isWidthDefined  = false;
1103   inputStyle.isSlantDefined  = false;
1104   inputStyle.isSizeDefined   = false;
1105
1106   inputStyle.isLineSpacingDefined = false;
1107
1108   inputStyle.isUnderlineDefined = false;
1109   inputStyle.isShadowDefined    = false;
1110   inputStyle.isEmbossDefined    = false;
1111   inputStyle.isOutlineDefined   = false;
1112
1113   // Sets the default font's family name, weight, width, slant and size.
1114   if(mFontDefaults)
1115   {
1116     if(mFontDefaults->familyDefined)
1117     {
1118       inputStyle.familyName      = mFontDefaults->mFontDescription.family;
1119       inputStyle.isFamilyDefined = true;
1120     }
1121
1122     if(mFontDefaults->weightDefined)
1123     {
1124       inputStyle.weight          = mFontDefaults->mFontDescription.weight;
1125       inputStyle.isWeightDefined = true;
1126     }
1127
1128     if(mFontDefaults->widthDefined)
1129     {
1130       inputStyle.width          = mFontDefaults->mFontDescription.width;
1131       inputStyle.isWidthDefined = true;
1132     }
1133
1134     if(mFontDefaults->slantDefined)
1135     {
1136       inputStyle.slant          = mFontDefaults->mFontDescription.slant;
1137       inputStyle.isSlantDefined = true;
1138     }
1139
1140     if(mFontDefaults->sizeDefined)
1141     {
1142       inputStyle.size          = mFontDefaults->mDefaultPointSize;
1143       inputStyle.isSizeDefined = true;
1144     }
1145   }
1146 }
1147
1148 float Controller::Impl::GetDefaultFontLineHeight()
1149 {
1150   FontId defaultFontId = 0u;
1151   if(nullptr == mFontDefaults)
1152   {
1153     TextAbstraction::FontDescription fontDescription;
1154     defaultFontId = mFontClient.GetFontId(fontDescription, TextAbstraction::FontClient::DEFAULT_POINT_SIZE * mFontSizeScale);
1155   }
1156   else
1157   {
1158     defaultFontId = mFontDefaults->GetFontId(mFontClient, mFontDefaults->mDefaultPointSize * mFontSizeScale);
1159   }
1160
1161   Text::FontMetrics fontMetrics;
1162   mMetrics->GetFontMetrics(defaultFontId, fontMetrics);
1163
1164   return (fontMetrics.ascender - fontMetrics.descender);
1165 }
1166
1167 void Controller::Impl::SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEnd)
1168 {
1169   if(nullptr == mEventData)
1170   {
1171     // Nothing to do if there is no text.
1172     return;
1173   }
1174
1175   if(mEventData->mSelectionEnabled && (pStart || pEnd))
1176   {
1177     uint32_t length = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
1178
1179     if(pStart)
1180     {
1181       mEventData->mLeftSelectionPosition = std::min(*pStart, length);
1182     }
1183     if(pEnd)
1184     {
1185       mEventData->mRightSelectionPosition = std::min(*pEnd, length);
1186     }
1187
1188     if(mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
1189     {
1190       ChangeState(EventData::EDITING);
1191       mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition;
1192       mEventData->mUpdateCursorPosition                                       = true;
1193     }
1194     else
1195     {
1196       ChangeState(EventData::SELECTING);
1197       mEventData->mUpdateHighlightBox           = true;
1198       mEventData->mUpdateLeftSelectionPosition  = true;
1199       mEventData->mUpdateRightSelectionPosition = true;
1200     }
1201   }
1202 }
1203
1204 CharacterIndex Controller::Impl::GetPrimaryCursorPosition() const
1205 {
1206   if(nullptr == mEventData)
1207   {
1208     return 0;
1209   }
1210   return mEventData->mPrimaryCursorPosition;
1211 }
1212
1213 bool Controller::Impl::SetPrimaryCursorPosition(CharacterIndex index)
1214 {
1215   if(nullptr == mEventData)
1216   {
1217     // Nothing to do if there is no text.
1218     return false;
1219   }
1220
1221   if(mEventData->mPrimaryCursorPosition == index)
1222   {
1223     // Nothing for same cursor position.
1224     return false;
1225   }
1226
1227   uint32_t length                    = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
1228   mEventData->mPrimaryCursorPosition = std::min(index, length);
1229   ChangeState(EventData::EDITING);
1230   mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
1231   mEventData->mUpdateCursorPosition                                        = true;
1232   ScrollTextToMatchCursor();
1233   return true;
1234 }
1235
1236 Uint32Pair Controller::Impl::GetTextSelectionRange() const
1237 {
1238   Uint32Pair range;
1239
1240   if(mEventData)
1241   {
1242     range.first  = mEventData->mLeftSelectionPosition;
1243     range.second = mEventData->mRightSelectionPosition;
1244   }
1245
1246   return range;
1247 }
1248
1249 bool Controller::Impl::IsEditable() const
1250 {
1251   return mEventData && mEventData->mEditingEnabled;
1252 }
1253
1254 void Controller::Impl::SetEditable(bool editable)
1255 {
1256   if(mEventData)
1257   {
1258     mEventData->mEditingEnabled = editable;
1259   }
1260 }
1261
1262 void Controller::Impl::RetrieveSelection(std::string& selectedText, bool deleteAfterRetrieval)
1263 {
1264   if(mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
1265   {
1266     // Nothing to select if handles are in the same place.
1267     selectedText.clear();
1268     return;
1269   }
1270
1271   const bool handlesCrossed = mEventData->mLeftSelectionPosition > mEventData->mRightSelectionPosition;
1272
1273   //Get start and end position of selection
1274   const CharacterIndex startOfSelectedText  = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
1275   const Length         lengthOfSelectedText = (handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition) - startOfSelectedText;
1276
1277   Vector<Character>& utf32Characters    = mModel->mLogicalModel->mText;
1278   const Length       numberOfCharacters = utf32Characters.Count();
1279
1280   // Validate the start and end selection points
1281   if((startOfSelectedText + lengthOfSelectedText) <= numberOfCharacters)
1282   {
1283     //Get text as a UTF8 string
1284     Utf32ToUtf8(&utf32Characters[startOfSelectedText], lengthOfSelectedText, selectedText);
1285
1286     if(deleteAfterRetrieval) // Only delete text if copied successfully
1287     {
1288       // Keep a copy of the current input style.
1289       InputStyle currentInputStyle;
1290       currentInputStyle.Copy(mEventData->mInputStyle);
1291
1292       // Set as input style the style of the first deleted character.
1293       mModel->mLogicalModel->RetrieveStyle(startOfSelectedText, mEventData->mInputStyle);
1294
1295       // Compare if the input style has changed.
1296       const bool hasInputStyleChanged = !currentInputStyle.Equal(mEventData->mInputStyle);
1297
1298       if(hasInputStyleChanged)
1299       {
1300         const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask(mEventData->mInputStyle);
1301         // Queue the input style changed signal.
1302         mEventData->mInputStyleChangedQueue.PushBack(styleChangedMask);
1303       }
1304
1305       mModel->mLogicalModel->UpdateTextStyleRuns(startOfSelectedText, -static_cast<int>(lengthOfSelectedText));
1306
1307       // Mark the paragraphs to be updated.
1308       if(Layout::Engine::SINGLE_LINE_BOX == mLayoutEngine.GetLayout())
1309       {
1310         mTextUpdateInfo.mCharacterIndex             = 0;
1311         mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
1312         mTextUpdateInfo.mNumberOfCharactersToAdd    = mTextUpdateInfo.mPreviousNumberOfCharacters - lengthOfSelectedText;
1313         mTextUpdateInfo.mClearAll                   = true;
1314       }
1315       else
1316       {
1317         mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
1318         mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
1319       }
1320
1321       // Delete text between handles
1322       Vector<Character>::Iterator first = utf32Characters.Begin() + startOfSelectedText;
1323       Vector<Character>::Iterator last  = first + lengthOfSelectedText;
1324       utf32Characters.Erase(first, last);
1325
1326       // Will show the cursor at the first character of the selection.
1327       mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
1328     }
1329     else
1330     {
1331       // Will show the cursor at the last character of the selection.
1332       mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition;
1333     }
1334
1335     mEventData->mDecoratorUpdated = true;
1336   }
1337 }
1338
1339 void Controller::Impl::SetSelection(int start, int end)
1340 {
1341   mEventData->mLeftSelectionPosition  = start;
1342   mEventData->mRightSelectionPosition = end;
1343   mEventData->mUpdateCursorPosition   = true;
1344 }
1345
1346 std::pair<int, int> Controller::Impl::GetSelectionIndexes() const
1347 {
1348   return {mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition};
1349 }
1350
1351 void Controller::Impl::ShowClipboard()
1352 {
1353   if(mClipboard)
1354   {
1355     mClipboard.ShowClipboard();
1356   }
1357 }
1358
1359 void Controller::Impl::HideClipboard()
1360 {
1361   if(mClipboard && mClipboardHideEnabled)
1362   {
1363     mClipboard.HideClipboard();
1364   }
1365 }
1366
1367 void Controller::Impl::SetClipboardHideEnable(bool enable)
1368 {
1369   mClipboardHideEnabled = enable;
1370 }
1371
1372 bool Controller::Impl::CopyStringToClipboard(const std::string& source)
1373 {
1374   //Send string to clipboard
1375   return (mClipboard && mClipboard.SetItem(source));
1376 }
1377
1378 void Controller::Impl::SendSelectionToClipboard(bool deleteAfterSending)
1379 {
1380   std::string selectedText;
1381   RetrieveSelection(selectedText, deleteAfterSending);
1382   CopyStringToClipboard(selectedText);
1383   ChangeState(EventData::EDITING);
1384 }
1385
1386 void Controller::Impl::RequestGetTextFromClipboard()
1387 {
1388   if(mClipboard)
1389   {
1390     mClipboard.RequestItem();
1391   }
1392 }
1393
1394 void Controller::Impl::RepositionSelectionHandles()
1395 {
1396   SelectionHandleController::Reposition(*this);
1397 }
1398 void Controller::Impl::RepositionSelectionHandles(float visualX, float visualY, Controller::NoTextTap::Action action)
1399 {
1400   SelectionHandleController::Reposition(*this, visualX, visualY, action);
1401 }
1402
1403 void Controller::Impl::SetPopupButtons()
1404 {
1405   /**
1406    *  Sets the Popup buttons to be shown depending on State.
1407    *
1408    *  If SELECTING :  CUT & COPY + ( PASTE & CLIPBOARD if content available to paste )
1409    *
1410    *  If EDITING_WITH_POPUP : SELECT & SELECT_ALL
1411    */
1412
1413   bool                        isEditable    = IsEditable();
1414   TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::NONE;
1415
1416   if(EventData::SELECTING == mEventData->mState)
1417   {
1418     buttonsToShow = TextSelectionPopup::Buttons(TextSelectionPopup::COPY);
1419     if(isEditable)
1420     {
1421       buttonsToShow = TextSelectionPopup::Buttons(buttonsToShow | TextSelectionPopup::CUT);
1422     }
1423
1424     if(!IsClipboardEmpty())
1425     {
1426       if(isEditable)
1427       {
1428         buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
1429       }
1430       buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
1431     }
1432
1433     if(!mEventData->mAllTextSelected)
1434     {
1435       buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::SELECT_ALL));
1436     }
1437   }
1438   else if(EventData::EDITING_WITH_POPUP == mEventData->mState)
1439   {
1440     if(mModel->mLogicalModel->mText.Count() && !IsShowingPlaceholderText())
1441     {
1442       buttonsToShow = TextSelectionPopup::Buttons(TextSelectionPopup::SELECT | TextSelectionPopup::SELECT_ALL);
1443     }
1444
1445     if(!IsClipboardEmpty())
1446     {
1447       if(isEditable)
1448       {
1449         buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
1450       }
1451       buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
1452     }
1453   }
1454   else if(EventData::EDITING_WITH_PASTE_POPUP == mEventData->mState)
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
1466   mEventData->mDecorator->SetEnabledPopupButtons(buttonsToShow);
1467 }
1468
1469 void Controller::Impl::ChangeState(EventData::State newState)
1470 {
1471   if(nullptr == mEventData)
1472   {
1473     // Nothing to do if there is no text input.
1474     return;
1475   }
1476
1477   DALI_LOG_INFO(gLogFilter, Debug::General, "ChangeState state:%d  newstate:%d\n", mEventData->mState, newState);
1478
1479   if(mEventData->mState != newState)
1480   {
1481     mEventData->mPreviousState = mEventData->mState;
1482     mEventData->mState         = newState;
1483
1484     switch(mEventData->mState)
1485     {
1486       case EventData::INACTIVE:
1487       {
1488         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
1489         mEventData->mDecorator->StopCursorBlink();
1490         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1491         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1492         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1493         mEventData->mDecorator->SetHighlightActive(false);
1494         mEventData->mDecorator->SetPopupActive(false);
1495         mEventData->mDecoratorUpdated = true;
1496         break;
1497       }
1498       case EventData::INTERRUPTED:
1499       {
1500         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1501         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1502         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1503         mEventData->mDecorator->SetHighlightActive(false);
1504         mEventData->mDecorator->SetPopupActive(false);
1505         mEventData->mDecoratorUpdated = true;
1506         break;
1507       }
1508       case EventData::SELECTING:
1509       {
1510         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
1511         mEventData->mDecorator->StopCursorBlink();
1512         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1513         if(mEventData->mGrabHandleEnabled)
1514         {
1515           mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
1516           mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
1517         }
1518         mEventData->mDecorator->SetHighlightActive(true);
1519         if(mEventData->mGrabHandlePopupEnabled)
1520         {
1521           SetPopupButtons();
1522           mEventData->mDecorator->SetPopupActive(true);
1523         }
1524         mEventData->mDecoratorUpdated = true;
1525         break;
1526       }
1527       case EventData::EDITING:
1528       {
1529         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1530         if(mEventData->mCursorBlinkEnabled)
1531         {
1532           mEventData->mDecorator->StartCursorBlink();
1533         }
1534         // Grab handle is not shown until a tap is received whilst EDITING
1535         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1536         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1537         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1538         mEventData->mDecorator->SetHighlightActive(false);
1539         if(mEventData->mGrabHandlePopupEnabled)
1540         {
1541           mEventData->mDecorator->SetPopupActive(false);
1542         }
1543         mEventData->mDecoratorUpdated = true;
1544         break;
1545       }
1546       case EventData::EDITING_WITH_POPUP:
1547       {
1548         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_POPUP \n", newState);
1549
1550         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1551         if(mEventData->mCursorBlinkEnabled)
1552         {
1553           mEventData->mDecorator->StartCursorBlink();
1554         }
1555         if(mEventData->mSelectionEnabled)
1556         {
1557           mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1558           mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1559           mEventData->mDecorator->SetHighlightActive(false);
1560         }
1561         else if(mEventData->mGrabHandleEnabled)
1562         {
1563           mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
1564         }
1565         if(mEventData->mGrabHandlePopupEnabled)
1566         {
1567           SetPopupButtons();
1568           mEventData->mDecorator->SetPopupActive(true);
1569         }
1570         mEventData->mDecoratorUpdated = true;
1571         break;
1572       }
1573       case EventData::EDITING_WITH_GRAB_HANDLE:
1574       {
1575         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_GRAB_HANDLE \n", newState);
1576
1577         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1578         if(mEventData->mCursorBlinkEnabled)
1579         {
1580           mEventData->mDecorator->StartCursorBlink();
1581         }
1582         // Grab handle is not shown until a tap is received whilst EDITING
1583         if(mEventData->mGrabHandleEnabled)
1584         {
1585           mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
1586         }
1587         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1588         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1589         mEventData->mDecorator->SetHighlightActive(false);
1590         if(mEventData->mGrabHandlePopupEnabled)
1591         {
1592           mEventData->mDecorator->SetPopupActive(false);
1593         }
1594         mEventData->mDecoratorUpdated = true;
1595         break;
1596       }
1597       case EventData::SELECTION_HANDLE_PANNING:
1598       {
1599         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
1600         mEventData->mDecorator->StopCursorBlink();
1601         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1602         if(mEventData->mGrabHandleEnabled)
1603         {
1604           mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
1605           mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
1606         }
1607         mEventData->mDecorator->SetHighlightActive(true);
1608         if(mEventData->mGrabHandlePopupEnabled)
1609         {
1610           mEventData->mDecorator->SetPopupActive(false);
1611         }
1612         mEventData->mDecoratorUpdated = true;
1613         break;
1614       }
1615       case EventData::GRAB_HANDLE_PANNING:
1616       {
1617         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "GRAB_HANDLE_PANNING \n", newState);
1618
1619         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1620         if(mEventData->mCursorBlinkEnabled)
1621         {
1622           mEventData->mDecorator->StartCursorBlink();
1623         }
1624         if(mEventData->mGrabHandleEnabled)
1625         {
1626           mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
1627         }
1628         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1629         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1630         mEventData->mDecorator->SetHighlightActive(false);
1631         if(mEventData->mGrabHandlePopupEnabled)
1632         {
1633           mEventData->mDecorator->SetPopupActive(false);
1634         }
1635         mEventData->mDecoratorUpdated = true;
1636         break;
1637       }
1638       case EventData::EDITING_WITH_PASTE_POPUP:
1639       {
1640         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_PASTE_POPUP \n", newState);
1641
1642         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1643         if(mEventData->mCursorBlinkEnabled)
1644         {
1645           mEventData->mDecorator->StartCursorBlink();
1646         }
1647
1648         if(mEventData->mGrabHandleEnabled)
1649         {
1650           mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
1651         }
1652         mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1653         mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1654         mEventData->mDecorator->SetHighlightActive(false);
1655
1656         if(mEventData->mGrabHandlePopupEnabled)
1657         {
1658           SetPopupButtons();
1659           mEventData->mDecorator->SetPopupActive(true);
1660         }
1661         mEventData->mDecoratorUpdated = true;
1662         break;
1663       }
1664       case EventData::TEXT_PANNING:
1665       {
1666         mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
1667         mEventData->mDecorator->StopCursorBlink();
1668         mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
1669         if(mEventData->mDecorator->IsHandleActive(LEFT_SELECTION_HANDLE) ||
1670            mEventData->mDecorator->IsHandleActive(RIGHT_SELECTION_HANDLE))
1671         {
1672           mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
1673           mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
1674           mEventData->mDecorator->SetHighlightActive(true);
1675         }
1676
1677         if(mEventData->mGrabHandlePopupEnabled)
1678         {
1679           mEventData->mDecorator->SetPopupActive(false);
1680         }
1681
1682         mEventData->mDecoratorUpdated = true;
1683         break;
1684       }
1685     }
1686   }
1687 }
1688
1689 void Controller::Impl::GetCursorPosition(CharacterIndex logical,
1690                                          CursorInfo&    cursorInfo)
1691 {
1692   if(!IsShowingRealText())
1693   {
1694     // Do not want to use the place-holder text to set the cursor position.
1695
1696     // Use the line's height of the font's family set to set the cursor's size.
1697     // If there is no font's family set, use the default font.
1698     // Use the current alignment to place the cursor at the beginning, center or end of the box.
1699
1700     cursorInfo.lineOffset          = 0.f;
1701     cursorInfo.lineHeight          = GetDefaultFontLineHeight();
1702     cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
1703
1704     bool isRTL = false;
1705     if(mModel->mMatchSystemLanguageDirection)
1706     {
1707       isRTL = mLayoutDirection == LayoutDirection::RIGHT_TO_LEFT;
1708     }
1709
1710     switch(mModel->mHorizontalAlignment)
1711     {
1712       case Text::HorizontalAlignment::BEGIN:
1713       {
1714         if(isRTL)
1715         {
1716           cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
1717         }
1718         else
1719         {
1720           cursorInfo.primaryPosition.x = 0.f;
1721         }
1722         break;
1723       }
1724       case Text::HorizontalAlignment::CENTER:
1725       {
1726         cursorInfo.primaryPosition.x = floorf(0.5f * mModel->mVisualModel->mControlSize.width);
1727         break;
1728       }
1729       case Text::HorizontalAlignment::END:
1730       {
1731         if(isRTL)
1732         {
1733           cursorInfo.primaryPosition.x = 0.f;
1734         }
1735         else
1736         {
1737           cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
1738         }
1739         break;
1740       }
1741     }
1742
1743     // Nothing else to do.
1744     return;
1745   }
1746
1747   const bool                  isMultiLine = (Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout());
1748   GetCursorPositionParameters parameters;
1749   parameters.visualModel  = mModel->mVisualModel;
1750   parameters.logicalModel = mModel->mLogicalModel;
1751   parameters.metrics      = mMetrics;
1752   parameters.logical      = logical;
1753   parameters.isMultiline  = isMultiLine;
1754
1755   Text::GetCursorPosition(parameters,
1756                           cursorInfo);
1757
1758   // Adds Outline offset.
1759   const float outlineWidth = static_cast<float>(mModel->GetOutlineWidth());
1760   cursorInfo.primaryPosition.x += outlineWidth;
1761   cursorInfo.primaryPosition.y += outlineWidth;
1762   cursorInfo.secondaryPosition.x += outlineWidth;
1763   cursorInfo.secondaryPosition.y += outlineWidth;
1764
1765   if(isMultiLine)
1766   {
1767     // If the text is editable and multi-line, the cursor position after a white space shouldn't exceed the boundaries of the text control.
1768
1769     // Note the white spaces laid-out at the end of the line might exceed the boundaries of the control.
1770     // The reason is a wrapped line must not start with a white space so they are laid-out at the end of the line.
1771
1772     if(0.f > cursorInfo.primaryPosition.x)
1773     {
1774       cursorInfo.primaryPosition.x = 0.f;
1775     }
1776
1777     const float edgeWidth = mModel->mVisualModel->mControlSize.width - static_cast<float>(mEventData->mDecorator->GetCursorWidth());
1778     if(cursorInfo.primaryPosition.x > edgeWidth)
1779     {
1780       cursorInfo.primaryPosition.x = edgeWidth;
1781     }
1782   }
1783 }
1784
1785 CharacterIndex Controller::Impl::CalculateNewCursorIndex(CharacterIndex index) const
1786 {
1787   if(nullptr == mEventData)
1788   {
1789     // Nothing to do if there is no text input.
1790     return 0u;
1791   }
1792
1793   CharacterIndex cursorIndex = mEventData->mPrimaryCursorPosition;
1794
1795   const GlyphIndex* const charactersToGlyphBuffer  = mModel->mVisualModel->mCharactersToGlyph.Begin();
1796   const Length* const     charactersPerGlyphBuffer = mModel->mVisualModel->mCharactersPerGlyph.Begin();
1797
1798   GlyphIndex glyphIndex         = *(charactersToGlyphBuffer + index);
1799   Length     numberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
1800
1801   if(numberOfCharacters > 1u)
1802   {
1803     const Script script = mModel->mLogicalModel->GetScript(index);
1804     if(HasLigatureMustBreak(script))
1805     {
1806       // Prevents to jump the whole Latin ligatures like fi, ff, or Arabic ï»», ...
1807       numberOfCharacters = 1u;
1808     }
1809   }
1810   else
1811   {
1812     while(0u == numberOfCharacters)
1813     {
1814       ++glyphIndex;
1815       numberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
1816     }
1817   }
1818
1819   if(index < mEventData->mPrimaryCursorPosition)
1820   {
1821     cursorIndex -= numberOfCharacters;
1822   }
1823   else
1824   {
1825     cursorIndex += numberOfCharacters;
1826   }
1827
1828   // Will update the cursor hook position.
1829   mEventData->mUpdateCursorHookPosition = true;
1830
1831   return cursorIndex;
1832 }
1833
1834 void Controller::Impl::UpdateCursorPosition(const CursorInfo& cursorInfo)
1835 {
1836   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::UpdateCursorPosition %p\n", this);
1837   if(nullptr == mEventData)
1838   {
1839     // Nothing to do if there is no text input.
1840     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition no event data\n");
1841     return;
1842   }
1843
1844   const Vector2 cursorPosition = cursorInfo.primaryPosition + mModel->mScrollPosition;
1845
1846   mEventData->mDecorator->SetGlyphOffset(PRIMARY_CURSOR, cursorInfo.glyphOffset);
1847
1848   // Sets the cursor position.
1849   mEventData->mDecorator->SetPosition(PRIMARY_CURSOR,
1850                                       cursorPosition.x,
1851                                       cursorPosition.y,
1852                                       cursorInfo.primaryCursorHeight,
1853                                       cursorInfo.lineHeight);
1854   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Primary cursor position: %f,%f\n", cursorPosition.x, cursorPosition.y);
1855
1856   if(mEventData->mUpdateGrabHandlePosition)
1857   {
1858     // Sets the grab handle position.
1859     mEventData->mDecorator->SetPosition(GRAB_HANDLE,
1860                                         cursorPosition.x,
1861                                         cursorInfo.lineOffset + mModel->mScrollPosition.y,
1862                                         cursorInfo.lineHeight);
1863   }
1864
1865   if(cursorInfo.isSecondaryCursor)
1866   {
1867     mEventData->mDecorator->SetPosition(SECONDARY_CURSOR,
1868                                         cursorInfo.secondaryPosition.x + mModel->mScrollPosition.x,
1869                                         cursorInfo.secondaryPosition.y + mModel->mScrollPosition.y,
1870                                         cursorInfo.secondaryCursorHeight,
1871                                         cursorInfo.lineHeight);
1872     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + mModel->mScrollPosition.x, cursorInfo.secondaryPosition.y + mModel->mScrollPosition.y);
1873   }
1874
1875   // Set which cursors are active according the state.
1876   if(EventData::IsEditingState(mEventData->mState) || (EventData::GRAB_HANDLE_PANNING == mEventData->mState))
1877   {
1878     if(cursorInfo.isSecondaryCursor)
1879     {
1880       mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_BOTH);
1881     }
1882     else
1883     {
1884       mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
1885     }
1886   }
1887   else
1888   {
1889     mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
1890   }
1891
1892   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition\n");
1893 }
1894
1895 void Controller::Impl::UpdateSelectionHandle(HandleType        handleType,
1896                                              const CursorInfo& cursorInfo)
1897 {
1898   SelectionHandleController::Update(*this, handleType, cursorInfo);
1899 }
1900
1901 void Controller::Impl::ClampHorizontalScroll(const Vector2& layoutSize)
1902 {
1903   // Clamp between -space & -alignment offset.
1904
1905   if(layoutSize.width > mModel->mVisualModel->mControlSize.width)
1906   {
1907     const float space         = (layoutSize.width - mModel->mVisualModel->mControlSize.width) + mModel->mAlignmentOffset;
1908     mModel->mScrollPosition.x = (mModel->mScrollPosition.x < -space) ? -space : mModel->mScrollPosition.x;
1909     mModel->mScrollPosition.x = (mModel->mScrollPosition.x > -mModel->mAlignmentOffset) ? -mModel->mAlignmentOffset : mModel->mScrollPosition.x;
1910
1911     mEventData->mDecoratorUpdated = true;
1912   }
1913   else
1914   {
1915     mModel->mScrollPosition.x = 0.f;
1916   }
1917 }
1918
1919 void Controller::Impl::ClampVerticalScroll(const Vector2& layoutSize)
1920 {
1921   if(Layout::Engine::SINGLE_LINE_BOX == mLayoutEngine.GetLayout())
1922   {
1923     // Nothing to do if the text is single line.
1924     return;
1925   }
1926
1927   // Clamp between -space & 0.
1928   if(layoutSize.height > mModel->mVisualModel->mControlSize.height)
1929   {
1930     const float space         = (layoutSize.height - mModel->mVisualModel->mControlSize.height);
1931     mModel->mScrollPosition.y = (mModel->mScrollPosition.y < -space) ? -space : mModel->mScrollPosition.y;
1932     mModel->mScrollPosition.y = (mModel->mScrollPosition.y > 0.f) ? 0.f : mModel->mScrollPosition.y;
1933
1934     mEventData->mDecoratorUpdated = true;
1935   }
1936   else
1937   {
1938     mModel->mScrollPosition.y = 0.f;
1939   }
1940 }
1941
1942 void Controller::Impl::ScrollToMakePositionVisible(const Vector2& position, float lineHeight)
1943 {
1944   const float cursorWidth = mEventData->mDecorator ? static_cast<float>(mEventData->mDecorator->GetCursorWidth()) : 0.f;
1945
1946   // position is in actor's coords.
1947   const float positionEndX = position.x + cursorWidth;
1948   const float positionEndY = position.y + lineHeight;
1949
1950   // Transform the position to decorator coords.
1951   const float decoratorPositionBeginX = position.x + mModel->mScrollPosition.x;
1952   const float decoratorPositionEndX   = positionEndX + mModel->mScrollPosition.x;
1953
1954   const float decoratorPositionBeginY = position.y + mModel->mScrollPosition.y;
1955   const float decoratorPositionEndY   = positionEndY + mModel->mScrollPosition.y;
1956
1957   if(decoratorPositionBeginX < 0.f)
1958   {
1959     mModel->mScrollPosition.x = -position.x;
1960   }
1961   else if(decoratorPositionEndX > mModel->mVisualModel->mControlSize.width)
1962   {
1963     mModel->mScrollPosition.x = mModel->mVisualModel->mControlSize.width - positionEndX;
1964   }
1965
1966   if(Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout())
1967   {
1968     if(decoratorPositionBeginY < 0.f)
1969     {
1970       mModel->mScrollPosition.y = -position.y;
1971     }
1972     else if(decoratorPositionEndY > mModel->mVisualModel->mControlSize.height)
1973     {
1974       mModel->mScrollPosition.y = mModel->mVisualModel->mControlSize.height - positionEndY;
1975     }
1976   }
1977 }
1978
1979 void Controller::Impl::ScrollTextToMatchCursor(const CursorInfo& cursorInfo)
1980 {
1981   // Get the current cursor position in decorator coords.
1982   const Vector2& currentCursorPosition = mEventData->mDecorator->GetPosition(PRIMARY_CURSOR);
1983
1984   const LineIndex lineIndex = mModel->mVisualModel->GetLineOfCharacter(mEventData->mPrimaryCursorPosition);
1985
1986   // Calculate the offset to match the cursor position before the character was deleted.
1987   mModel->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x;
1988
1989   //If text control has more than two lines and current line index is not last, calculate scrollpositionY
1990   if(mModel->mVisualModel->mLines.Count() > 1u && lineIndex != mModel->mVisualModel->mLines.Count() - 1u)
1991   {
1992     const float currentCursorGlyphOffset = mEventData->mDecorator->GetGlyphOffset(PRIMARY_CURSOR);
1993     mModel->mScrollPosition.y            = currentCursorPosition.y - cursorInfo.lineOffset - currentCursorGlyphOffset;
1994   }
1995
1996   ClampHorizontalScroll(mModel->mVisualModel->GetLayoutSize());
1997   ClampVerticalScroll(mModel->mVisualModel->GetLayoutSize());
1998
1999   // Makes the new cursor position visible if needed.
2000   ScrollToMakePositionVisible(cursorInfo.primaryPosition, cursorInfo.lineHeight);
2001 }
2002
2003 void Controller::Impl::ScrollTextToMatchCursor()
2004 {
2005   CursorInfo cursorInfo;
2006   GetCursorPosition(mEventData->mPrimaryCursorPosition, cursorInfo);
2007   ScrollTextToMatchCursor(cursorInfo);
2008 }
2009
2010 void Controller::Impl::RequestRelayout()
2011 {
2012   if(nullptr != mControlInterface)
2013   {
2014     mControlInterface->RequestTextRelayout();
2015   }
2016 }
2017
2018 Actor Controller::Impl::CreateBackgroundActor()
2019 {
2020   // NOTE: Currently we only support background color for left-to-right text.
2021
2022   Actor actor;
2023
2024   Length numberOfGlyphs = mView.GetNumberOfGlyphs();
2025   if(numberOfGlyphs > 0u)
2026   {
2027     Vector<GlyphInfo> glyphs;
2028     glyphs.Resize(numberOfGlyphs);
2029
2030     Vector<Vector2> positions;
2031     positions.Resize(numberOfGlyphs);
2032
2033     // Get the line where the glyphs are laid-out.
2034     const LineRun* lineRun         = mModel->mVisualModel->mLines.Begin();
2035     float          alignmentOffset = lineRun->alignmentOffset;
2036     numberOfGlyphs                 = mView.GetGlyphs(glyphs.Begin(),
2037                                      positions.Begin(),
2038                                      alignmentOffset,
2039                                      0u,
2040                                      numberOfGlyphs);
2041
2042     glyphs.Resize(numberOfGlyphs);
2043     positions.Resize(numberOfGlyphs);
2044
2045     const GlyphInfo* const glyphsBuffer    = glyphs.Begin();
2046     const Vector2* const   positionsBuffer = positions.Begin();
2047
2048     BackgroundMesh mesh;
2049     mesh.mVertices.Reserve(4u * glyphs.Size());
2050     mesh.mIndices.Reserve(6u * glyphs.Size());
2051
2052     const Vector2 textSize = mView.GetLayoutSize();
2053
2054     const float offsetX = textSize.width * 0.5f;
2055     const float offsetY = textSize.height * 0.5f;
2056
2057     const Vector4* const    backgroundColorsBuffer       = mView.GetBackgroundColors();
2058     const ColorIndex* const backgroundColorIndicesBuffer = mView.GetBackgroundColorIndices();
2059     const Vector4&          defaultBackgroundColor       = mModel->mVisualModel->IsBackgroundEnabled() ? mModel->mVisualModel->GetBackgroundColor() : Color::TRANSPARENT;
2060
2061     Vector4   quad;
2062     uint32_t  numberOfQuads = 0u;
2063     Length    yLineOffset   = 0;
2064     Length    prevLineIndex = 0;
2065     LineIndex lineIndex;
2066     Length    numberOfLines;
2067
2068     for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i)
2069     {
2070       const GlyphInfo& glyph = *(glyphsBuffer + i);
2071
2072       // Get the background color of the character.
2073       // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT)
2074       const ColorIndex backgroundColorIndex = (nullptr == backgroundColorsBuffer) ? 0u : *(backgroundColorIndicesBuffer + i);
2075       const Vector4&   backgroundColor      = (0u == backgroundColorIndex) ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u);
2076
2077       mModel->mVisualModel->GetNumberOfLines(i, 1, lineIndex, numberOfLines);
2078       Length lineHeight = lineRun[lineIndex].ascender + -(lineRun[lineIndex].descender) + lineRun[lineIndex].lineSpacing;
2079
2080       if(lineIndex != prevLineIndex)
2081       {
2082         yLineOffset += lineHeight;
2083       }
2084
2085       // Only create quads for glyphs with a background color
2086       if(backgroundColor != Color::TRANSPARENT)
2087       {
2088         const Vector2 position = *(positionsBuffer + i);
2089
2090         if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text
2091         {
2092           quad.x = position.x;
2093           quad.y = yLineOffset;
2094           quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
2095           quad.w = lineHeight;
2096         }
2097         else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line
2098         {
2099           quad.x = position.x;
2100           quad.y = yLineOffset;
2101           quad.z = quad.x - glyph.xBearing + glyph.advance;
2102           quad.w = quad.y + lineHeight;
2103         }
2104         else if(i == glyphSize - 1u) // The last glyph in the whole text
2105         {
2106           quad.x = position.x - glyph.xBearing;
2107           quad.y = yLineOffset;
2108           quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
2109           quad.w = quad.y + lineHeight;
2110         }
2111         else // The glyph in the middle of the text
2112         {
2113           quad.x = position.x - glyph.xBearing;
2114           quad.y = yLineOffset;
2115           quad.z = quad.x + glyph.advance;
2116           quad.w = quad.y + lineHeight;
2117         }
2118
2119         BackgroundVertex vertex;
2120
2121         // Top left
2122         vertex.mPosition.x = quad.x - offsetX;
2123         vertex.mPosition.y = quad.y - offsetY;
2124         vertex.mColor      = backgroundColor;
2125         mesh.mVertices.PushBack(vertex);
2126
2127         // Top right
2128         vertex.mPosition.x = quad.z - offsetX;
2129         vertex.mPosition.y = quad.y - offsetY;
2130         vertex.mColor      = backgroundColor;
2131         mesh.mVertices.PushBack(vertex);
2132
2133         // Bottom left
2134         vertex.mPosition.x = quad.x - offsetX;
2135         vertex.mPosition.y = quad.w - offsetY;
2136         vertex.mColor      = backgroundColor;
2137         mesh.mVertices.PushBack(vertex);
2138
2139         // Bottom right
2140         vertex.mPosition.x = quad.z - offsetX;
2141         vertex.mPosition.y = quad.w - offsetY;
2142         vertex.mColor      = backgroundColor;
2143         mesh.mVertices.PushBack(vertex);
2144
2145         // Six indices in counter clockwise winding
2146         mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
2147         mesh.mIndices.PushBack(0u + 4 * numberOfQuads);
2148         mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
2149         mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
2150         mesh.mIndices.PushBack(3u + 4 * numberOfQuads);
2151         mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
2152
2153         numberOfQuads++;
2154       }
2155
2156       if(lineIndex != prevLineIndex)
2157       {
2158         prevLineIndex = lineIndex;
2159       }
2160     }
2161
2162     // Only create the background actor if there are glyphs with background color
2163     if(mesh.mVertices.Count() > 0u)
2164     {
2165       Property::Map quadVertexFormat;
2166       quadVertexFormat["aPosition"] = Property::VECTOR2;
2167       quadVertexFormat["aColor"]    = Property::VECTOR4;
2168
2169       VertexBuffer quadVertices = VertexBuffer::New(quadVertexFormat);
2170       quadVertices.SetData(&mesh.mVertices[0], mesh.mVertices.Size());
2171
2172       Geometry quadGeometry = Geometry::New();
2173       quadGeometry.AddVertexBuffer(quadVertices);
2174       quadGeometry.SetIndexBuffer(&mesh.mIndices[0], mesh.mIndices.Size());
2175
2176       if(!mShaderBackground)
2177       {
2178         mShaderBackground = Shader::New(SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_VERT, SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_FRAG);
2179       }
2180
2181       Dali::Renderer renderer = Dali::Renderer::New(quadGeometry, mShaderBackground);
2182       renderer.SetProperty(Dali::Renderer::Property::BLEND_MODE, BlendMode::ON);
2183       renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT);
2184
2185       actor = Actor::New();
2186       actor.SetProperty(Dali::Actor::Property::NAME, "TextBackgroundColorActor");
2187       actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
2188       actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
2189       actor.SetProperty(Actor::Property::SIZE, textSize);
2190       actor.SetProperty(Actor::Property::COLOR_MODE, USE_OWN_MULTIPLY_PARENT_COLOR);
2191       actor.AddRenderer(renderer);
2192     }
2193   }
2194
2195   return actor;
2196 }
2197
2198 void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns)
2199 {
2200   //Underlined character runs for markup-processor
2201   const Vector<UnderlinedCharacterRun>& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns;
2202   const Vector<GlyphIndex>&             charactersToGlyph       = mModel->mVisualModel->mCharactersToGlyph;
2203   const Vector<Length>&                 glyphsPerCharacter      = mModel->mVisualModel->mGlyphsPerCharacter;
2204
2205   if(shouldClearPreUnderlineRuns)
2206   {
2207     mModel->mVisualModel->mUnderlineRuns.Clear();
2208   }
2209
2210   for(Vector<UnderlinedCharacterRun>::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it)
2211   {
2212     CharacterIndex characterIndex     = it->characterRun.characterIndex;
2213     Length         numberOfCharacters = it->characterRun.numberOfCharacters;
2214     for(Length index = 0u; index < numberOfCharacters; index++)
2215     {
2216       GlyphRun underlineGlyphRun;
2217       underlineGlyphRun.glyphIndex     = charactersToGlyph[characterIndex + index];
2218       underlineGlyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index];
2219       mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
2220     }
2221   }
2222 }
2223
2224 } // namespace Text
2225
2226 } // namespace Toolkit
2227
2228 } // namespace Dali