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