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