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