Internal text model inteface.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller.cpp
1 /*
2  * Copyright (c) 2015 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.h>
20
21 // EXTERNAL INCLUDES
22 #include <limits>
23 #include <vector>
24 #include <dali/public-api/adaptor-framework/key.h>
25 #include <dali/public-api/text-abstraction/font-client.h>
26
27 // INTERNAL INCLUDES
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/layouts/layout-engine.h>
31 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
32 #include <dali-toolkit/internal/text/logical-model-impl.h>
33 #include <dali-toolkit/internal/text/multi-language-support.h>
34 #include <dali-toolkit/internal/text/script-run.h>
35 #include <dali-toolkit/internal/text/segmentation.h>
36 #include <dali-toolkit/internal/text/shaper.h>
37 #include <dali-toolkit/internal/text/text-view.h>
38 #include <dali-toolkit/internal/text/visual-model-impl.h>
39
40 using std::vector;
41
42 namespace
43 {
44 const float MAX_FLOAT = std::numeric_limits<float>::max();
45 const std::string EMPTY_STRING;
46 } // namespace
47
48 namespace Dali
49 {
50
51 namespace Toolkit
52 {
53
54 namespace Text
55 {
56
57 struct Controller::TextInput
58 {
59   // Used to queue input events until DoRelayout()
60   enum EventType
61   {
62     KEYBOARD_FOCUS_GAIN_EVENT,
63     KEYBOARD_FOCUS_LOST_EVENT,
64     KEY_EVENT,
65     TAP_EVENT,
66     GRAB_HANDLE_EVENT
67   };
68
69   union Param
70   {
71     int mInt;
72     unsigned int mUint;
73     float mFloat;
74     char* mString;
75   };
76
77   struct Event
78   {
79     Event( EventType eventType )
80     : type( eventType )
81     {
82       p1.mInt = 0;
83       p2.mInt = 0;
84     }
85
86     EventType type;
87     Param p1;
88     Param p2;
89     Param p3;
90   };
91
92   enum State
93   {
94     INACTIVE,
95     SELECTING,
96     EDITING
97   };
98
99   TextInput( LogicalModelPtr logicalModel,
100              VisualModelPtr visualModel,
101              DecoratorPtr decorator )
102   : mLogicalModel( logicalModel ),
103     mVisualModel( visualModel ),
104     mDecorator( decorator ),
105     mState( INACTIVE ),
106     mDecoratorUpdated( false ),
107     mCursorBlinkEnabled( true )
108   {
109   }
110
111   /**
112    * @brief Helper to move the cursor, grab handle etc.
113    */
114   bool ProcessInputEvents()
115   {
116     mDecoratorUpdated = false;
117
118     if( mDecorator )
119     {
120       for( vector<TextInput::Event>::iterator iter = mEventQueue.begin(); iter != mEventQueue.end(); ++iter )
121       {
122         switch( iter->type )
123         {
124           case KEYBOARD_FOCUS_GAIN_EVENT:
125           {
126             OnKeyboardFocus( true );
127             break;
128           }
129           case KEYBOARD_FOCUS_LOST_EVENT:
130           {
131             OnKeyboardFocus( false );
132             break;
133           }
134           case KEY_EVENT:
135           {
136             OnKeyEvent( *iter );
137             break;
138           }
139           case TAP_EVENT:
140           {
141             OnTapEvent( *iter );
142             break;
143           }
144           case GRAB_HANDLE_EVENT:
145           {
146             OnGrabHandleEvent( *iter );
147             break;
148           }
149         }
150       }
151     }
152
153     mEventQueue.clear();
154
155     return mDecoratorUpdated;
156   }
157
158   void OnKeyboardFocus( bool hasFocus )
159   {
160     if( !hasFocus )
161     {
162       ChangeState( INACTIVE );
163     }
164     else
165     {
166       ChangeState( EDITING );
167     }
168   }
169
170   void OnKeyEvent( const Event& event )
171   {
172     int keyCode = event.p1.mInt;
173
174     // Handle state changes
175     if( Dali::DALI_KEY_ESCAPE == keyCode )
176     {
177       ChangeState( INACTIVE ); // Escape key ends edit mode
178     }
179     else if ( event.p2.mString )
180     {
181       // Some text may be selected, hiding keyboard causes an empty keystring to be sent, we don't want to delete highlight in this case
182       ChangeState( EDITING );
183     }
184
185     // Handle the actual key event
186     if( Dali::DALI_KEY_BACKSPACE == keyCode )
187     {
188       HandleBackspaceKey();
189     }
190     else if( Dali::DALI_KEY_CURSOR_LEFT  == keyCode ||
191              Dali::DALI_KEY_CURSOR_RIGHT == keyCode ||
192              Dali::DALI_KEY_CURSOR_UP    == keyCode ||
193              Dali::DALI_KEY_CURSOR_DOWN  == keyCode )
194     {
195       HandleCursorKey( keyCode );
196     }
197     else if ( event.p2.mString )
198     {
199       HandleKeyString( event.p2.mString );
200
201       delete [] event.p2.mString;
202     }
203   }
204
205   void HandleBackspaceKey()
206   {
207     // TODO
208   }
209
210   void HandleCursorKey( int keyCode )
211   {
212     // TODO
213   }
214
215   void HandleKeyString( const char* keyString )
216   {
217     // TODO
218   }
219
220   void OnTapEvent( const Event& event )
221   {
222     unsigned int tapCount = event.p1.mUint;
223
224     if( 1u == tapCount )
225     {
226       ChangeState( EDITING );
227
228       float xPosition = event.p2.mFloat;
229       float yPosition = event.p3.mFloat;
230       float height(0.0f);
231       GetClosestCursorPosition( xPosition, yPosition, height );
232       mDecorator->SetPosition( PRIMARY_CURSOR, xPosition, yPosition, height );
233
234       mDecoratorUpdated = true;
235     }
236     else if( 2u == tapCount )
237     {
238       ChangeState( SELECTING );
239     }
240   }
241
242   void OnGrabHandleEvent( const Event& event )
243   {
244     unsigned int state = event.p1.mUint;
245
246     if( GRAB_HANDLE_PRESSED == state )
247     {
248       float xPosition = event.p2.mFloat;
249       float yPosition = event.p3.mFloat;
250       float height(0.0f);
251
252       GetClosestCursorPosition( xPosition, yPosition, height );
253
254       mDecorator->SetPosition( PRIMARY_CURSOR, xPosition, yPosition, height );
255       mDecorator->HidePopup();
256       mDecoratorUpdated = true;
257     }
258     else if ( GRAB_HANDLE_RELEASED == state )
259     {
260       mDecorator->ShowPopup();
261     }
262
263   }
264
265   void ChangeState( State newState )
266   {
267     if( mState != newState )
268     {
269       mState = newState;
270
271       if( INACTIVE == mState )
272       {
273         mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
274         mDecorator->StopCursorBlink();
275         mDecorator->SetGrabHandleActive( false );
276         mDecorator->SetSelectionActive( false );
277         mDecorator->HidePopup();
278         mDecoratorUpdated = true;
279       }
280       else if ( SELECTING == mState )
281       {
282         mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
283         mDecorator->StopCursorBlink();
284         mDecorator->SetGrabHandleActive( false );
285         mDecorator->SetSelectionActive( true );
286         mDecoratorUpdated = true;
287       }
288       else if( EDITING == mState )
289       {
290         mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY );
291         if( mCursorBlinkEnabled )
292         {
293           mDecorator->StartCursorBlink();
294         }
295         mDecorator->SetGrabHandleActive( true );
296         mDecorator->SetSelectionActive( false );
297         mDecoratorUpdated = true;
298       }
299     }
300   }
301
302   void GetClosestCursorPosition( float& x, float& y, float& height )
303   {
304     // TODO - Look at LineRuns first
305
306     Text::Length numberOfGlyphs = mVisualModel->GetNumberOfGlyphs();
307     if( 0 == numberOfGlyphs )
308     {
309       return;
310     }
311
312     Vector<GlyphInfo>& glyphs = mVisualModel->mGlyphs;
313     const GlyphInfo* const glyphsBuffer = glyphs.Begin();
314
315     Vector<Vector2>& positions = mVisualModel->mGlyphPositions;
316     const Vector2* const positionsBuffer = positions.Begin();
317
318     unsigned int closestGlyph = 0;
319     float closestDistance = MAX_FLOAT;
320
321     for( unsigned int i = 0, numberOfGLyphs = glyphs.Count(); i < numberOfGLyphs; ++i )
322     {
323       const GlyphInfo& glyphInfo = *( glyphsBuffer + i );
324       const Vector2& position = *( positionsBuffer + i );
325       float glyphX = position.x + glyphInfo.width*0.5f;
326       float glyphY = position.y + glyphInfo.height*0.5f;
327
328       float distanceToGlyph = fabsf( glyphX - x ) + fabsf( glyphY - y );
329
330       if( distanceToGlyph < closestDistance )
331       {
332         closestDistance = distanceToGlyph;
333         closestGlyph = i;
334       }
335     }
336
337     // TODO - Consider RTL languages
338     x = positions[closestGlyph].x + glyphs[closestGlyph].width;
339     y = 0.0f;
340
341     FontMetrics metrics;
342     TextAbstraction::FontClient::Get().GetFontMetrics( glyphs[closestGlyph].fontId, metrics );
343     height = metrics.height; // TODO - Fix for multi-line
344   }
345
346   LogicalModelPtr mLogicalModel;
347   VisualModelPtr  mVisualModel;
348   DecoratorPtr    mDecorator;
349
350   std::string mPlaceholderText;
351
352   /**
353    * This is used to delay handling events until after the model has been updated.
354    * The number of updates to the model is minimized to improve performance.
355    */
356   vector<Event> mEventQueue; ///< The queue of touch events etc.
357
358   State mState;
359
360   bool mDecoratorUpdated   : 1;
361   bool mCursorBlinkEnabled : 1;
362 };
363
364 struct Controller::FontDefaults
365 {
366   FontDefaults()
367   : mDefaultPointSize(0.0f),
368     mFontId(0u)
369   {
370   }
371
372   FontId GetFontId( TextAbstraction::FontClient& fontClient )
373   {
374     if( !mFontId )
375     {
376       Dali::TextAbstraction::PointSize26Dot6 pointSize = mDefaultPointSize*64;
377       mFontId = fontClient.GetFontId( mDefaultFontFamily, mDefaultFontStyle, pointSize );
378     }
379
380     return mFontId;
381   }
382
383   std::string mDefaultFontFamily;
384   std::string mDefaultFontStyle;
385   float mDefaultPointSize;
386   FontId mFontId;
387 };
388
389 struct Controller::Impl
390 {
391   Impl( ControlInterface& controlInterface )
392   : mControlInterface( controlInterface ),
393     mLogicalModel(),
394     mVisualModel(),
395     mFontDefaults( NULL ),
396     mTextInput( NULL ),
397     mFontClient(),
398     mView(),
399     mLayoutEngine(),
400     mNewText(),
401     mControlSize(),
402     mOperationsPending( NO_OPERATION ),
403     mRecalculateNaturalSize( true )
404   {
405     mLogicalModel = LogicalModel::New();
406     mVisualModel  = VisualModel::New();
407
408     mFontClient = TextAbstraction::FontClient::Get();
409
410     mView.SetVisualModel( mVisualModel );
411   }
412
413   ~Impl()
414   {
415     delete mTextInput;
416   }
417
418   ControlInterface& mControlInterface;     ///< Reference to the text controller.
419   LogicalModelPtr mLogicalModel;           ///< Pointer to the logical model.
420   VisualModelPtr  mVisualModel;            ///< Pointer to the visual model.
421   FontDefaults* mFontDefaults;             ///< Avoid allocating this when the user does not specify a font.
422   Controller::TextInput* mTextInput;       ///< Avoid allocating everything for text input until EnableTextInput().
423   TextAbstraction::FontClient mFontClient; ///< Handle to the font client.
424   View mView;                              ///< The view interface to the rendering back-end.
425   LayoutEngine mLayoutEngine;              ///< The layout engine.
426   std::string mNewText;                    ///< Temporary stores the text set until the next relayout.
427   Size mControlSize;                       ///< The size of the control.
428   OperationsMask mOperationsPending;       ///< Operations pending to be done to layout the text.
429   bool mRecalculateNaturalSize:1;          ///< Whether the natural size needs to be recalculated.
430 };
431
432 ControllerPtr Controller::New( ControlInterface& controlInterface )
433 {
434   return ControllerPtr( new Controller( controlInterface ) );
435 }
436
437 void Controller::SetText( const std::string& text )
438 {
439   // Keep until size negotiation
440   mImpl->mNewText = text;
441
442   // All operations need to be done. (convert to utf32, get break info, ..., layout, ...)
443   mImpl->mOperationsPending = ALL_OPERATIONS;
444
445   // The natural size needs to be re-calculated.
446   mImpl->mRecalculateNaturalSize = true;
447
448   // Reset buffers.
449   mImpl->mLogicalModel->SetText( NULL, 0u );
450   mImpl->mLogicalModel->SetScripts( NULL, 0u );
451   mImpl->mLogicalModel->SetFonts( NULL, 0u );
452   mImpl->mLogicalModel->SetLineBreakInfo( NULL, 0u );
453   mImpl->mLogicalModel->SetWordBreakInfo( NULL, 0u );
454   mImpl->mLogicalModel->SetBidirectionalInfo( NULL, 0u );
455   mImpl->mLogicalModel->SetVisualToLogicalMap( NULL, 0u );
456   mImpl->mVisualModel->SetGlyphs( NULL, NULL, NULL, 0u );
457   mImpl->mVisualModel->SetGlyphPositions( NULL, 0u );
458   mImpl->mVisualModel->SetLines( NULL, 0u );
459
460   if( mImpl->mTextInput )
461   {
462     // Cancel previously queued events
463     mImpl->mTextInput->mEventQueue.clear();
464
465     // TODO - Hide selection decorations
466   }
467 }
468
469 void Controller::GetText( std::string& text ) const
470 {
471   if( !mImpl->mNewText.empty() )
472   {
473     text = mImpl->mNewText;
474   }
475   else
476   {
477     // TODO - Convert from UTF-32
478   }
479 }
480
481 void Controller::SetPlaceholderText( const std::string& text )
482 {
483   if( !mImpl->mTextInput )
484   {
485     mImpl->mTextInput->mPlaceholderText = text;
486   }
487 }
488
489 void Controller::GetPlaceholderText( std::string& text ) const
490 {
491   if( !mImpl->mTextInput )
492   {
493     text = mImpl->mTextInput->mPlaceholderText;
494   }
495 }
496
497 void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily )
498 {
499   if( !mImpl->mFontDefaults )
500   {
501     mImpl->mFontDefaults = new Controller::FontDefaults();
502   }
503
504   mImpl->mFontDefaults->mDefaultFontFamily = defaultFontFamily;
505   mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
506   mImpl->mOperationsPending = ALL_OPERATIONS;
507   mImpl->mRecalculateNaturalSize = true;
508 }
509
510 const std::string& Controller::GetDefaultFontFamily() const
511 {
512   if( mImpl->mFontDefaults )
513   {
514     return mImpl->mFontDefaults->mDefaultFontFamily;
515   }
516
517   return EMPTY_STRING;
518 }
519
520 void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle )
521 {
522   if( !mImpl->mFontDefaults )
523   {
524     mImpl->mFontDefaults = new Controller::FontDefaults();
525   }
526
527   mImpl->mFontDefaults->mDefaultFontStyle = defaultFontStyle;
528   mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
529   mImpl->mOperationsPending = ALL_OPERATIONS;
530   mImpl->mRecalculateNaturalSize = true;
531 }
532
533 const std::string& Controller::GetDefaultFontStyle() const
534 {
535   if( mImpl->mFontDefaults )
536   {
537     return mImpl->mFontDefaults->mDefaultFontStyle;
538   }
539
540   return EMPTY_STRING;
541 }
542
543 void Controller::SetDefaultPointSize( float pointSize )
544 {
545   if( !mImpl->mFontDefaults )
546   {
547     mImpl->mFontDefaults = new Controller::FontDefaults();
548   }
549
550   mImpl->mFontDefaults->mDefaultPointSize = pointSize;
551   mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
552   mImpl->mOperationsPending = ALL_OPERATIONS;
553   mImpl->mRecalculateNaturalSize = true;
554 }
555
556 float Controller::GetDefaultPointSize() const
557 {
558   if( mImpl->mFontDefaults )
559   {
560     return mImpl->mFontDefaults->mDefaultPointSize;
561   }
562
563   return 0.0f;
564 }
565
566 void Controller::GetDefaultFonts( Vector<FontRun>& fonts, Length numberOfCharacters )
567 {
568   if( mImpl->mFontDefaults )
569   {
570     FontRun fontRun;
571     fontRun.characterRun.characterIndex = 0;
572     fontRun.characterRun.numberOfCharacters = numberOfCharacters;
573     fontRun.fontId = mImpl->mFontDefaults->GetFontId( mImpl->mFontClient );
574     fontRun.isDefault = true;
575
576     fonts.PushBack( fontRun );
577   }
578 }
579
580 void Controller::EnableTextInput( DecoratorPtr decorator )
581 {
582   if( !mImpl->mTextInput )
583   {
584     mImpl->mTextInput = new TextInput( mImpl->mLogicalModel, mImpl->mVisualModel, decorator );
585   }
586 }
587
588 void Controller::SetEnableCursorBlink( bool enable )
589 {
590   DALI_ASSERT_DEBUG( NULL != mImpl->mTextInput && "TextInput disabled" );
591
592   if( mImpl->mTextInput )
593   {
594     mImpl->mTextInput->mCursorBlinkEnabled = enable;
595
596     if( !enable &&
597         mImpl->mTextInput->mDecorator )
598     {
599       mImpl->mTextInput->mDecorator->StopCursorBlink();
600     }
601   }
602 }
603
604 bool Controller::GetEnableCursorBlink() const
605 {
606   if( mImpl->mTextInput )
607   {
608     return mImpl->mTextInput->mCursorBlinkEnabled;
609   }
610
611   return false;
612 }
613
614 Vector3 Controller::GetNaturalSize()
615 {
616   Vector3 naturalSize;
617
618   if( mImpl->mRecalculateNaturalSize )
619   {
620     // Operations that can be done only once until the text changes.
621     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
622                                                                            GET_SCRIPTS       |
623                                                                            VALIDATE_FONTS    |
624                                                                            GET_LINE_BREAKS   |
625                                                                            GET_WORD_BREAKS   |
626                                                                            SHAPE_TEXT        |
627                                                                            GET_GLYPH_METRICS );
628     // Make sure the model is up-to-date before layouting
629     ReplaceText( onlyOnceOperations );
630
631     // Operations that need to be done if the size changes.
632     const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
633                                                                         REORDER );
634
635     DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
636                 static_cast<OperationsMask>( onlyOnceOperations |
637                                              sizeOperations ),
638                 naturalSize.GetVectorXY() );
639
640     // Do not do again the only once operations.
641     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
642
643     // Do the size related operations again.
644     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
645
646     // Stores the natural size to avoid recalculate it again
647     // unless the text/style changes.
648     mImpl->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() );
649
650     mImpl->mRecalculateNaturalSize = false;
651   }
652   else
653   {
654     naturalSize = mImpl->mVisualModel->GetNaturalSize();
655   }
656
657   return naturalSize;
658 }
659
660 float Controller::GetHeightForWidth( float width )
661 {
662   Size layoutSize;
663   if( width != mImpl->mControlSize.width )
664   {
665     // Operations that can be done only once until the text changes.
666     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
667                                                                            GET_SCRIPTS       |
668                                                                            VALIDATE_FONTS    |
669                                                                            GET_LINE_BREAKS   |
670                                                                            GET_WORD_BREAKS   |
671                                                                            SHAPE_TEXT        |
672                                                                            GET_GLYPH_METRICS );
673
674     // Make sure the model is up-to-date before layouting
675     ReplaceText( onlyOnceOperations );
676
677     // Operations that need to be done if the size changes.
678     const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
679                                                                         REORDER );
680
681     DoRelayout( Size( width, MAX_FLOAT ),
682                 static_cast<OperationsMask>( onlyOnceOperations |
683                                              sizeOperations ),
684                 layoutSize );
685
686     // Do not do again the only once operations.
687     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
688
689     // Do the size related operations again.
690     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
691   }
692   else
693   {
694     layoutSize = mImpl->mVisualModel->GetActualSize();
695   }
696
697   return layoutSize.height;
698 }
699
700 bool Controller::Relayout( const Vector2& size )
701 {
702   if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
703   {
704     bool glyphsRemoved( false );
705     if( 0u != mImpl->mVisualModel->GetNumberOfGlyphPositions() )
706     {
707       mImpl->mVisualModel->SetGlyphPositions( NULL, 0u );
708       glyphsRemoved = true;
709     }
710
711     // Not worth to relayout if width or height is equal to zero.
712     return glyphsRemoved;
713   }
714
715   if( size != mImpl->mControlSize )
716   {
717     // Operations that need to be done if the size changes.
718     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
719                                                              LAYOUT                    |
720                                                              UPDATE_ACTUAL_SIZE        |
721                                                              REORDER );
722
723     mImpl->mControlSize = size;
724   }
725
726   // Make sure the model is up-to-date before layouting
727   ReplaceText( mImpl->mOperationsPending );
728
729   Size layoutSize;
730   bool updated = DoRelayout( mImpl->mControlSize,
731                              mImpl->mOperationsPending,
732                              layoutSize );
733
734   // Do not re-do any operation until something changes.
735   mImpl->mOperationsPending = NO_OPERATION;
736
737   if( mImpl->mTextInput )
738   {
739     // Move the cursor, grab handle etc.
740     updated = mImpl->mTextInput->ProcessInputEvents() || updated;
741   }
742
743   return updated;
744 }
745
746 void Controller::ReplaceText( OperationsMask operationsRequired )
747 {
748   // Calculate the operations to be done.
749   const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
750
751   Vector<Character>& utf32Characters = mImpl->mLogicalModel->mText;
752   if( CONVERT_TO_UTF32 & operations )
753   {
754     std::string& text = mImpl->mNewText;
755
756     //  Convert text into UTF-32
757     utf32Characters.Resize( text.size() );
758
759     // This is a bit horrible but std::string returns a (signed) char*
760     const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
761
762     // Transform a text array encoded in utf8 into an array encoded in utf32.
763     // It returns the actual number of characters.
764     const Length characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() );
765     utf32Characters.Resize( characterCount );
766
767     // Discard temporary text
768     text.clear();
769   }
770
771   const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
772
773   Vector<LineBreakInfo>& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo;
774   if( GET_LINE_BREAKS & operations )
775   {
776     // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
777     // calculate the bidirectional info for each 'paragraph'.
778     // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
779     // is not shaped together).
780     lineBreakInfo.Resize( numberOfCharacters, TextAbstraction::LINE_NO_BREAK );
781
782     SetLineBreakInfo( utf32Characters,
783                       lineBreakInfo );
784   }
785
786   Vector<WordBreakInfo>& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo;
787   if( GET_WORD_BREAKS & operations )
788   {
789     // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
790     wordBreakInfo.Resize( numberOfCharacters, TextAbstraction::WORD_NO_BREAK );
791
792     SetWordBreakInfo( utf32Characters,
793                       wordBreakInfo );
794   }
795
796   const bool getScripts = GET_SCRIPTS & operations;
797   const bool validateFonts = VALIDATE_FONTS & operations;
798
799   Vector<ScriptRun>& scripts = mImpl->mLogicalModel->mScriptRuns;
800   Vector<FontRun>& validFonts = mImpl->mLogicalModel->mFontRuns;
801
802   if( getScripts || validateFonts )
803   {
804     // Validates the fonts assigned by the application or assigns default ones.
805     // It makes sure all the characters are going to be rendered by the correct font.
806     MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
807
808     if( getScripts )
809     {
810       // Retrieves the scripts used in the text.
811       multilanguageSupport.SetScripts( utf32Characters,
812                                        lineBreakInfo,
813                                        scripts );
814     }
815
816     if( validateFonts )
817     {
818       if( 0u == validFonts.Count() )
819       {
820         // Copy the requested font defaults received via the property system.
821         // These may not be valid i.e. may not contain glyphs for the necessary scripts.
822         GetDefaultFonts( validFonts, numberOfCharacters );
823       }
824
825       // Validates the fonts. If there is a character with no assigned font it sets a default one.
826       // After this call, fonts are validated.
827       multilanguageSupport.ValidateFonts( utf32Characters,
828                                           scripts,
829                                           validFonts );
830     }
831   }
832
833   if( BIDI_INFO & operations )
834   {
835     // Count the number of LINE_NO_BREAK to reserve some space for the vector of paragraph's
836     // bidirectional info.
837
838     Length numberOfParagraphs = 0u;
839
840     const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
841     for( Length index = 0u; index < numberOfCharacters; ++index )
842     {
843       if( TextAbstraction::LINE_NO_BREAK == *( lineBreakInfoBuffer + index ) )
844       {
845         ++numberOfParagraphs;
846       }
847     }
848
849     Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo;
850     bidirectionalInfo.Reserve( numberOfParagraphs );
851
852     // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
853     SetBidirectionalInfo( utf32Characters,
854                           scripts,
855                           lineBreakInfo,
856                           bidirectionalInfo );
857   }
858
859   Vector<GlyphInfo>& glyphs = mImpl->mVisualModel->mGlyphs;
860   Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters;
861   Vector<Length>& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph;
862   if( SHAPE_TEXT & operations )
863   {
864     // Shapes the text.
865     ShapeText( utf32Characters,
866                lineBreakInfo,
867                scripts,
868                validFonts,
869                glyphs,
870                glyphsToCharactersMap,
871                charactersPerGlyph );
872   }
873
874   const Length numberOfGlyphs = glyphs.Count();
875
876   if( GET_GLYPH_METRICS & operations )
877   {
878     mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), numberOfGlyphs );
879   }
880
881   if( 0u != numberOfGlyphs )
882   {
883     // Create the glyph to character conversion table and the 'number of glyphs' per character.
884     mImpl->mVisualModel->CreateCharacterToGlyphTable(numberOfCharacters );
885     mImpl->mVisualModel->CreateGlyphsPerCharacterTable( numberOfCharacters );
886   }
887 }
888
889 bool Controller::DoRelayout( const Vector2& size,
890                              OperationsMask operationsRequired,
891                              Size& layoutSize )
892 {
893   bool viewUpdated( false );
894
895   // Calculate the operations to be done.
896   const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
897
898   if( LAYOUT & operations )
899   {
900     // Some vectors with data needed to layout and reorder may be void
901     // after the first time the text has been laid out.
902     // Fill the vectors again.
903
904     const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
905     Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
906
907     Vector<LineBreakInfo>& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo;
908     Vector<WordBreakInfo>& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo;
909     Vector<GlyphInfo>& glyphs = mImpl->mVisualModel->mGlyphs;
910     Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters;
911     Vector<Length>& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph;
912
913     // Set the layout parameters.
914     LayoutParameters layoutParameters( size,
915                                        lineBreakInfo.Begin(),
916                                        wordBreakInfo.Begin(),
917                                        numberOfGlyphs,
918                                        glyphs.Begin(),
919                                        glyphsToCharactersMap.Begin(),
920                                        charactersPerGlyph.Begin() );
921
922     // The laid-out lines.
923     // It's not possible to know in how many lines the text is going to be laid-out,
924     // but it can be resized at least with the number of 'paragraphs' to avoid
925     // some re-allocations.
926     Vector<LineRun>& lines = mImpl->mVisualModel->mLines;
927
928     // Resize the vector of positions to have the same size than the vector of glyphs.
929     Vector<Vector2>& glyphPositions = mImpl->mVisualModel->mGlyphPositions;
930     glyphPositions.Resize( numberOfGlyphs );
931
932     BidirectionalRunIndex firstBidiRunIndex = 0u;
933     Length numberOfBidiRuns = 0u;
934     mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters, firstBidiRunIndex, numberOfBidiRuns );
935
936     // Delete any previous laid out lines before setting the new ones.
937     lines.Clear();
938     lines.Reserve( numberOfBidiRuns );
939
940     // Update the visual model.
941     viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters,
942                                                    glyphPositions,
943                                                    lines,
944                                                    layoutSize );
945
946     if( viewUpdated )
947     {
948       // Reorder the lines
949       if( REORDER & operations )
950       {
951         Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo;
952
953         // Check first if there are paragraphs with bidirectional info.
954         if( 0u != bidirectionalInfo.Count() )
955         {
956           // Get the lines
957           const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines();
958
959           // Reorder the lines.
960           Vector<BidirectionalLineInfoRun> lineBidirectionalInfoRuns;
961           lineBidirectionalInfoRuns.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
962           ReorderLines( bidirectionalInfo,
963                         lines,
964                         lineBidirectionalInfoRuns );
965
966           // Set the bidirectional info into the model.
967           const Length numberOfBidirectionalInfoRuns = lineBidirectionalInfoRuns.Count();
968           mImpl->mLogicalModel->SetVisualToLogicalMap( lineBidirectionalInfoRuns.Begin(),
969                                                        numberOfBidirectionalInfoRuns );
970
971           // Set the bidirectional info per line into the layout parameters.
972           layoutParameters.lineBidirectionalInfoRunsBuffer = lineBidirectionalInfoRuns.Begin();
973           layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns;
974
975           // Get the character to glyph conversion table and set into the layout.
976           layoutParameters.charactersToGlyphsBuffer = mImpl->mVisualModel->mCharactersToGlyph.Begin();
977
978           // Get the glyphs per character table and set into the layout.
979           layoutParameters.glyphsPerCharacterBuffer = mImpl->mVisualModel->mGlyphsPerCharacter.Begin();
980
981           // Re-layout the text. Reorder those lines with right to left characters.
982           mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters,
983                                                          glyphPositions );
984
985           // Free the allocated memory used to store the conversion table in the bidirectional line info run.
986           for( Vector<BidirectionalLineInfoRun>::Iterator it = lineBidirectionalInfoRuns.Begin(),
987                  endIt = lineBidirectionalInfoRuns.End();
988                it != endIt;
989                ++it )
990           {
991             BidirectionalLineInfoRun& bidiLineInfo = *it;
992
993             free( bidiLineInfo.visualToLogicalMap );
994           }
995         }
996       }
997
998       // Sets the actual size.
999       if( UPDATE_ACTUAL_SIZE & operations )
1000       {
1001         mImpl->mVisualModel->SetActualSize( layoutSize );
1002       }
1003     }
1004   }
1005   else
1006   {
1007     layoutSize = mImpl->mVisualModel->GetActualSize();
1008   }
1009
1010   return viewUpdated;
1011 }
1012
1013 View& Controller::GetView()
1014 {
1015   return mImpl->mView;
1016 }
1017
1018 LayoutEngine& Controller::GetLayoutEngine()
1019 {
1020   return mImpl->mLayoutEngine;
1021 }
1022
1023 void Controller::RequestRelayout()
1024 {
1025   mImpl->mControlInterface.RequestTextRelayout();
1026 }
1027
1028 void Controller::KeyboardFocusGainEvent()
1029 {
1030   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusGainEvent" );
1031
1032   if( mImpl->mTextInput )
1033   {
1034     TextInput::Event event( TextInput::KEYBOARD_FOCUS_GAIN_EVENT );
1035     mImpl->mTextInput->mEventQueue.push_back( event );
1036
1037     RequestRelayout();
1038   }
1039 }
1040
1041 void Controller::KeyboardFocusLostEvent()
1042 {
1043   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusLostEvent" );
1044
1045   if( mImpl->mTextInput )
1046   {
1047     TextInput::Event event( TextInput::KEYBOARD_FOCUS_LOST_EVENT );
1048     mImpl->mTextInput->mEventQueue.push_back( event );
1049
1050     RequestRelayout();
1051   }
1052 }
1053
1054 bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
1055 {
1056   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyEvent" );
1057
1058   if( mImpl->mTextInput )
1059   {
1060     TextInput::Event event( TextInput::KEY_EVENT );
1061     event.p1.mInt = keyEvent.keyCode;
1062     event.p2.mString = NULL;
1063
1064     const std::string& keyString = keyEvent.keyPressed;
1065     if ( !keyString.empty() )
1066     {
1067       event.p2.mString = new char[keyString.size() + 1];
1068       std::copy(keyString.begin(), keyString.end(), event.p2.mString);
1069       event.p2.mString[keyString.size()] = '\0';
1070     }
1071
1072     mImpl->mTextInput->mEventQueue.push_back( event );
1073
1074     RequestRelayout();
1075   }
1076
1077   return false;
1078 }
1079
1080 void Controller::TapEvent( unsigned int tapCount, float x, float y )
1081 {
1082   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected TapEvent" );
1083
1084   if( mImpl->mTextInput )
1085   {
1086     TextInput::Event event( TextInput::TAP_EVENT );
1087     event.p1.mUint = tapCount;
1088     event.p2.mFloat = x;
1089     event.p3.mFloat = y;
1090     mImpl->mTextInput->mEventQueue.push_back( event );
1091
1092     RequestRelayout();
1093   }
1094 }
1095
1096 void Controller::GrabHandleEvent( GrabHandleState state, float x, float y )
1097 {
1098   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected GrabHandleEvent" );
1099
1100   if( mImpl->mTextInput )
1101   {
1102     TextInput::Event event( TextInput::GRAB_HANDLE_EVENT );
1103     event.p1.mUint  = state;
1104     event.p2.mFloat = x;
1105     event.p3.mFloat = y;
1106     mImpl->mTextInput->mEventQueue.push_back( event );
1107
1108     RequestRelayout();
1109   }
1110 }
1111
1112 Controller::~Controller()
1113 {
1114   delete mImpl;
1115 }
1116
1117 Controller::Controller( ControlInterface& controlInterface )
1118 : mImpl( NULL )
1119 {
1120   mImpl = new Controller::Impl( controlInterface );
1121 }
1122
1123 } // namespace Text
1124
1125 } // namespace Toolkit
1126
1127 } // namespace Dali