Prefer color Emoji by default
[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       mDecoratorUpdated = true;
245     }
246   }
247
248   void ChangeState( State newState )
249   {
250     if( mState != newState )
251     {
252       mState = newState;
253
254       if( INACTIVE == mState )
255       {
256         mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
257         mDecorator->StopCursorBlink();
258         mDecorator->SetGrabHandleActive( false );
259         mDecorator->SetSelectionActive( false );
260         mDecoratorUpdated = true;
261       }
262       else if ( SELECTING == mState )
263       {
264         mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
265         mDecorator->StopCursorBlink();
266         mDecorator->SetGrabHandleActive( false );
267         mDecorator->SetSelectionActive( true );
268         mDecoratorUpdated = true;
269       }
270       else if( EDITING == mState )
271       {
272         mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY );
273         mDecorator->StartCursorBlink();
274         mDecorator->SetGrabHandleActive( true );
275         mDecorator->SetSelectionActive( false );
276         mDecoratorUpdated = true;
277       }
278     }
279   }
280
281   void GetClosestCursorPosition( float& x, float& y, float& height )
282   {
283     // TODO - Look at LineRuns first
284
285     Text::Length numberOfGlyphs = mVisualModel->GetNumberOfGlyphs();
286     if( 0 == numberOfGlyphs )
287     {
288       return;
289     }
290
291     Vector<GlyphInfo> glyphs;
292     glyphs.Resize( numberOfGlyphs );
293     mVisualModel->GetGlyphs( glyphs.Begin(), 0, numberOfGlyphs );
294     const GlyphInfo* const glyphsBuffer = glyphs.Begin();
295
296     Vector<Vector2> positions;
297     positions.Resize( numberOfGlyphs );
298     mVisualModel->GetGlyphPositions( positions.Begin(), 0, numberOfGlyphs );
299     const Vector2* const positionsBuffer = positions.Begin();
300
301     unsigned int closestGlyph = 0;
302     float closestDistance = MAX_FLOAT;
303
304     for( unsigned int i = 0, numberOfGLyphs = glyphs.Count(); i < numberOfGLyphs; ++i )
305     {
306       const GlyphInfo& glyphInfo = *( glyphsBuffer + i );
307       const Vector2& position = *( positionsBuffer + i );
308       float glyphX = position.x + glyphInfo.width*0.5f;
309       float glyphY = position.y + glyphInfo.height*0.5f;
310
311       float distanceToGlyph = fabsf( glyphX - x ) + fabsf( glyphY - y );
312
313       if( distanceToGlyph < closestDistance )
314       {
315         closestDistance = distanceToGlyph;
316         closestGlyph = i;
317       }
318     }
319
320     // TODO - Consider RTL languages
321     x = positions[closestGlyph].x + glyphs[closestGlyph].width;
322     y = 0.0f;
323
324     FontMetrics metrics;
325     TextAbstraction::FontClient::Get().GetFontMetrics( glyphs[closestGlyph].fontId, metrics );
326     height = metrics.height; // TODO - Fix for multi-line
327   }
328
329   LogicalModelPtr mLogicalModel;
330   VisualModelPtr  mVisualModel;
331   DecoratorPtr    mDecorator;
332
333   std::string mPlaceholderText;
334
335   /**
336    * This is used to delay handling events until after the model has been updated.
337    * The number of updates to the model is minimized to improve performance.
338    */
339   vector<Event> mEventQueue; ///< The queue of touch events etc.
340
341   State mState;
342
343   bool mDecoratorUpdated;
344 };
345
346 struct Controller::FontDefaults
347 {
348   FontDefaults()
349   : mDefaultPointSize(0.0f),
350     mFontId(0u)
351   {
352   }
353
354   FontId GetFontId( TextAbstraction::FontClient& fontClient )
355   {
356     if( !mFontId )
357     {
358       Dali::TextAbstraction::PointSize26Dot6 pointSize = mDefaultPointSize*64;
359       mFontId = fontClient.GetFontId( mDefaultFontFamily, mDefaultFontStyle, pointSize );
360     }
361
362     return mFontId;
363   }
364
365   std::string mDefaultFontFamily;
366   std::string mDefaultFontStyle;
367   float mDefaultPointSize;
368   FontId mFontId;
369 };
370
371 struct Controller::Impl
372 {
373   Impl( ControlInterface& controlInterface )
374   : mControlInterface( controlInterface ),
375     mLogicalModel(),
376     mVisualModel(),
377     mFontDefaults( NULL ),
378     mTextInput( NULL ),
379     mFontClient(),
380     mView(),
381     mLayoutEngine(),
382     mNewText(),
383     mControlSize(),
384     mOperationsPending( NO_OPERATION ),
385     mRecalculateNaturalSize( true )
386   {
387     mLogicalModel = LogicalModel::New();
388     mVisualModel  = VisualModel::New();
389
390     mFontClient = TextAbstraction::FontClient::Get();
391
392     mView.SetVisualModel( mVisualModel );
393   }
394
395   ~Impl()
396   {
397     delete mTextInput;
398   }
399
400   ControlInterface& mControlInterface;     ///< Reference to the text controller.
401   LogicalModelPtr mLogicalModel;           ///< Pointer to the logical model.
402   VisualModelPtr  mVisualModel;            ///< Pointer to the visual model.
403   FontDefaults* mFontDefaults;             ///< Avoid allocating this when the user does not specify a font.
404   Controller::TextInput* mTextInput;       ///< Avoid allocating everything for text input until EnableTextInput().
405   TextAbstraction::FontClient mFontClient; ///< Handle to the font client.
406   View mView;                              ///< The view interface to the rendering back-end.
407   LayoutEngine mLayoutEngine;              ///< The layout engine.
408   std::string mNewText;                    ///< Temporary stores the text set until the next relayout.
409   Size mControlSize;                       ///< The size of the control.
410   OperationsMask mOperationsPending;       ///< Operations pending to be done to layout the text.
411   bool mRecalculateNaturalSize:1;          ///< Whether the natural size needs to be recalculated.
412 };
413
414 ControllerPtr Controller::New( ControlInterface& controlInterface )
415 {
416   return ControllerPtr( new Controller( controlInterface ) );
417 }
418
419 void Controller::SetText( const std::string& text )
420 {
421   // Keep until size negotiation
422   mImpl->mNewText = text;
423
424   // All operations need to be done. (convert to utf32, get break info, ..., layout, ...)
425   mImpl->mOperationsPending = ALL_OPERATIONS;
426
427   // The natural size needs to be re-calculated.
428   mImpl->mRecalculateNaturalSize = true;
429
430   if( mImpl->mTextInput )
431   {
432     // Cancel previously queued events
433     mImpl->mTextInput->mEventQueue.clear();
434
435     // TODO - Hide selection decorations
436   }
437 }
438
439 void Controller::GetText( std::string& text ) const
440 {
441   if( !mImpl->mNewText.empty() )
442   {
443     text = mImpl->mNewText;
444   }
445   else
446   {
447     // TODO - Convert from UTF-32
448   }
449 }
450
451 void Controller::SetPlaceholderText( const std::string& text )
452 {
453   if( !mImpl->mTextInput )
454   {
455     mImpl->mTextInput->mPlaceholderText = text;
456   }
457 }
458
459 void Controller::GetPlaceholderText( std::string& text ) const
460 {
461   if( !mImpl->mTextInput )
462   {
463     text = mImpl->mTextInput->mPlaceholderText;
464   }
465 }
466
467 void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily )
468 {
469   if( !mImpl->mFontDefaults )
470   {
471     mImpl->mFontDefaults = new Controller::FontDefaults();
472   }
473
474   mImpl->mFontDefaults->mDefaultFontFamily = defaultFontFamily;
475   mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
476   mImpl->mOperationsPending = ALL_OPERATIONS;
477   mImpl->mRecalculateNaturalSize = true;
478 }
479
480 const std::string& Controller::GetDefaultFontFamily() const
481 {
482   if( mImpl->mFontDefaults )
483   {
484     return mImpl->mFontDefaults->mDefaultFontFamily;
485   }
486
487   return EMPTY_STRING;
488 }
489
490 void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle )
491 {
492   if( !mImpl->mFontDefaults )
493   {
494     mImpl->mFontDefaults = new Controller::FontDefaults();
495   }
496
497   mImpl->mFontDefaults->mDefaultFontStyle = defaultFontStyle;
498   mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
499   mImpl->mOperationsPending = ALL_OPERATIONS;
500   mImpl->mRecalculateNaturalSize = true;
501 }
502
503 const std::string& Controller::GetDefaultFontStyle() const
504 {
505   if( mImpl->mFontDefaults )
506   {
507     return mImpl->mFontDefaults->mDefaultFontStyle;
508   }
509
510   return EMPTY_STRING;
511 }
512
513 void Controller::SetDefaultPointSize( float pointSize )
514 {
515   if( !mImpl->mFontDefaults )
516   {
517     mImpl->mFontDefaults = new Controller::FontDefaults();
518   }
519
520   mImpl->mFontDefaults->mDefaultPointSize = pointSize;
521   mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
522   mImpl->mOperationsPending = ALL_OPERATIONS;
523   mImpl->mRecalculateNaturalSize = true;
524 }
525
526 float Controller::GetDefaultPointSize() const
527 {
528   if( mImpl->mFontDefaults )
529   {
530     return mImpl->mFontDefaults->mDefaultPointSize;
531   }
532
533   return 0.0f;
534 }
535
536 void Controller::EnableTextInput( DecoratorPtr decorator )
537 {
538   if( !mImpl->mTextInput )
539   {
540     mImpl->mTextInput = new TextInput( mImpl->mLogicalModel, mImpl->mVisualModel, decorator );
541   }
542 }
543
544 bool Controller::Relayout( const Vector2& size )
545 {
546   if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
547   {
548     // Not worth to relayout if width or height is equal to zero.
549     return false;
550   }
551
552   if( size != mImpl->mControlSize )
553   {
554     // Operations that need to be done if the size changes.
555     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
556                                                              LAYOUT                    |
557                                                              UPDATE_ACTUAL_SIZE        |
558                                                              UPDATE_POSITIONS          |
559                                                              UPDATE_LINES              |
560                                                              REORDER );
561
562     mImpl->mControlSize = size;
563   }
564
565   Size layoutSize;
566   bool updated = DoRelayout( mImpl->mControlSize,
567                              mImpl->mOperationsPending,
568                              layoutSize );
569
570   // Do not re-do any operation until something changes.
571   mImpl->mOperationsPending = NO_OPERATION;
572
573   if( mImpl->mTextInput )
574   {
575     // Move the cursor, grab handle etc.
576     updated = mImpl->mTextInput->ProcessInputEvents() || updated;
577   }
578
579   return updated;
580 }
581
582 bool Controller::DoRelayout( const Vector2& size,
583                              OperationsMask operationsRequired,
584                              Size& layoutSize )
585 {
586   bool viewUpdated( false );
587
588   // Calculate the operations to be done.
589   const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
590
591   Vector<Character> utf32Characters;
592   Length characterCount = 0u;
593   if( CONVERT_TO_UTF32 & operations )
594   {
595     std::string& text = mImpl->mNewText;
596
597     //  Convert text into UTF-32
598     utf32Characters.Resize( text.size() );
599
600     // This is a bit horrible but std::string returns a (signed) char*
601     const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
602
603     // Transform a text array encoded in utf8 into an array encoded in utf32.
604     // It returns the actual number of characters.
605     characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() );
606     utf32Characters.Resize( characterCount );
607
608     // Sets the text into the model.
609     mImpl->mLogicalModel->SetText( utf32Characters.Begin(), characterCount );
610
611     // Discard temporary text
612     text.clear();
613   }
614
615   Vector<LineBreakInfo> lineBreakInfo;
616   if( GET_LINE_BREAKS & operations )
617   {
618     // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
619     // calculate the bidirectional info for each 'paragraph'.
620     // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
621     // is not shaped together).
622     lineBreakInfo.Resize( characterCount, TextAbstraction::LINE_NO_BREAK );
623
624     SetLineBreakInfo( utf32Characters,
625                       lineBreakInfo );
626
627     mImpl->mLogicalModel->SetLineBreakInfo( lineBreakInfo.Begin(), characterCount );
628   }
629
630   Vector<WordBreakInfo> wordBreakInfo;
631   if( GET_WORD_BREAKS & operations )
632   {
633     // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
634     wordBreakInfo.Resize( characterCount, TextAbstraction::WORD_NO_BREAK );
635
636     SetWordBreakInfo( utf32Characters,
637                       wordBreakInfo );
638
639     mImpl->mLogicalModel->SetWordBreakInfo( wordBreakInfo.Begin(), characterCount );
640   }
641
642   const bool getScripts = GET_SCRIPTS & operations;
643   const bool validateFonts = VALIDATE_FONTS & operations;
644
645   Vector<ScriptRun> scripts;
646   Vector<FontRun> fonts;
647
648   if( mImpl->mFontDefaults )
649   {
650     // TODO - pass into ValidateFonts
651   }
652
653   if( getScripts || validateFonts )
654   {
655     // Validates the fonts assigned by the application or assigns default ones.
656     // It makes sure all the characters are going to be rendered by the correct font.
657     MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
658
659     if( getScripts )
660     {
661       // Retrieves the scripts used in the text.
662       multilanguageSupport.SetScripts( utf32Characters,
663                                        lineBreakInfo,
664                                        scripts );
665
666       // Sets the scripts into the model.
667       mImpl->mLogicalModel->SetScripts( scripts.Begin(), scripts.Count() );
668     }
669
670     if( validateFonts )
671     {
672       // Validates the fonts. If there is a character with no assigned font it sets a default one.
673       // After this call, fonts are validated.
674       multilanguageSupport.ValidateFonts( utf32Characters,
675                                           scripts,
676                                           fonts );
677
678       // Sets the fonts into the model.
679       mImpl->mLogicalModel->SetFonts( fonts.Begin(), fonts.Count() );
680     }
681   }
682
683   Vector<GlyphInfo> glyphs;
684   Vector<CharacterIndex> glyphsToCharactersMap;
685   Vector<Length> charactersPerGlyph;
686   if( SHAPE_TEXT & operations )
687   {
688     // Shapes the text.
689     ShapeText( utf32Characters,
690                lineBreakInfo,
691                scripts,
692                fonts,
693                glyphs,
694                glyphsToCharactersMap,
695                charactersPerGlyph );
696   }
697
698   if( GET_GLYPH_METRICS & operations )
699   {
700     mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), glyphs.Count() );
701   }
702
703   Length numberOfGlyphs = glyphs.Count();
704   if( 0u != numberOfGlyphs )
705   {
706     // Sets the glyphs into the model.
707     mImpl->mVisualModel->SetGlyphs( glyphs.Begin(),
708                                     glyphsToCharactersMap.Begin(),
709                                     charactersPerGlyph.Begin(),
710                                     numberOfGlyphs );
711   }
712
713   if( LAYOUT & operations )
714   {
715     const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
716
717     if( 0u == numberOfGlyphs )
718     {
719       numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
720
721       lineBreakInfo.Resize( numberOfCharacters );
722       wordBreakInfo.Resize( numberOfCharacters );
723       glyphs.Resize( numberOfGlyphs );
724       glyphsToCharactersMap.Resize( numberOfGlyphs );
725       charactersPerGlyph.Resize( numberOfGlyphs );
726
727       mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(),
728                                               0u,
729                                               numberOfCharacters );
730
731       mImpl->mLogicalModel->GetWordBreakInfo( wordBreakInfo.Begin(),
732                                               0u,
733                                               numberOfCharacters );
734
735       mImpl->mVisualModel->GetGlyphs( glyphs.Begin(),
736                                       0u,
737                                       numberOfGlyphs );
738
739       mImpl->mVisualModel->GetGlyphToCharacterMap( glyphsToCharactersMap.Begin(),
740                                                    0u,
741                                                    numberOfGlyphs );
742
743       mImpl->mVisualModel->GetCharactersPerGlyphMap( charactersPerGlyph.Begin(),
744                                                      0u,
745                                                      numberOfGlyphs );
746     }
747
748     // Set the layout parameters.
749     LayoutParameters layoutParameters( size,
750                                        lineBreakInfo.Begin(),
751                                        wordBreakInfo.Begin(),
752                                        numberOfGlyphs,
753                                        glyphs.Begin(),
754                                        glyphsToCharactersMap.Begin(),
755                                        charactersPerGlyph.Begin() );
756
757     // Reserve space to set the positions of the glyphs.
758     Vector<Vector2> glyphPositions;
759     glyphPositions.Resize( numberOfGlyphs );
760
761     // The laid-out lines.
762     // It's not possible to know in how many lines the text is going to be laid-out,
763     // but it can be resized at least with the number of 'paragraphs' to avoid
764     // some re-allocations.
765     Vector<LineRun> lines;
766     lines.Reserve( mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters ) );
767
768     // Update the visual model.
769     viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters,
770                                                    glyphPositions,
771                                                    lines,
772                                                    layoutSize );
773
774     if( viewUpdated )
775     {
776       // Sets the positions into the model.
777       if( UPDATE_POSITIONS & operations )
778       {
779         mImpl->mVisualModel->SetGlyphPositions( glyphPositions.Begin(),
780                                                 numberOfGlyphs );
781       }
782
783       // Sets the lines into the model.
784       if( UPDATE_LINES & operations )
785       {
786         mImpl->mVisualModel->SetLines( lines.Begin(),
787                                        lines.Count() );
788       }
789
790       // Sets the actual size.
791       if( UPDATE_ACTUAL_SIZE & operations )
792       {
793         mImpl->mVisualModel->SetActualSize( layoutSize );
794       }
795     }
796   }
797   else
798   {
799     layoutSize = mImpl->mVisualModel->GetActualSize();
800   }
801
802   return viewUpdated;
803 }
804
805 Vector3 Controller::GetNaturalSize()
806 {
807   Vector3 naturalSize;
808
809   if( mImpl->mRecalculateNaturalSize )
810   {
811     // Operations that can be done only once until the text changes.
812     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
813                                                                            GET_SCRIPTS       |
814                                                                            VALIDATE_FONTS    |
815                                                                            GET_LINE_BREAKS   |
816                                                                            GET_WORD_BREAKS   |
817                                                                            SHAPE_TEXT        |
818                                                                            GET_GLYPH_METRICS );
819
820     // Operations that need to be done if the size changes.
821     const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
822                                                                         REORDER );
823
824     DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
825                 static_cast<OperationsMask>( onlyOnceOperations |
826                                              sizeOperations ),
827                 naturalSize.GetVectorXY() );
828
829     // Do not do again the only once operations.
830     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
831
832     // Do the size related operations again.
833     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
834
835     // Stores the natural size to avoid recalculate it again
836     // unless the text/style changes.
837     mImpl->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() );
838
839     mImpl->mRecalculateNaturalSize = false;
840   }
841   else
842   {
843     naturalSize = mImpl->mVisualModel->GetNaturalSize();
844   }
845
846   return naturalSize;
847 }
848
849 float Controller::GetHeightForWidth( float width )
850 {
851   Size layoutSize;
852   if( width != mImpl->mControlSize.width )
853   {
854     // Operations that can be done only once until the text changes.
855     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
856                                                                            GET_SCRIPTS       |
857                                                                            VALIDATE_FONTS    |
858                                                                            GET_LINE_BREAKS   |
859                                                                            GET_WORD_BREAKS   |
860                                                                            SHAPE_TEXT        |
861                                                                            GET_GLYPH_METRICS );
862
863     // Operations that need to be done if the size changes.
864     const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
865                                                                         REORDER );
866
867     DoRelayout( Size( width, MAX_FLOAT ),
868                 static_cast<OperationsMask>( onlyOnceOperations |
869                                              sizeOperations ),
870                 layoutSize );
871
872     // Do not do again the only once operations.
873     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
874
875     // Do the size related operations again.
876     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
877   }
878   else
879   {
880     layoutSize = mImpl->mVisualModel->GetActualSize();
881   }
882
883   return layoutSize.height;
884 }
885
886 View& Controller::GetView()
887 {
888   return mImpl->mView;
889 }
890
891 LayoutEngine& Controller::GetLayoutEngine()
892 {
893   return mImpl->mLayoutEngine;
894 }
895
896 void Controller::RequestRelayout()
897 {
898   mImpl->mControlInterface.RequestTextRelayout();
899 }
900
901 void Controller::KeyboardFocusGainEvent()
902 {
903   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusGainEvent" );
904
905   if( mImpl->mTextInput )
906   {
907     TextInput::Event event( TextInput::KEYBOARD_FOCUS_GAIN_EVENT );
908     mImpl->mTextInput->mEventQueue.push_back( event );
909
910     RequestRelayout();
911   }
912 }
913
914 void Controller::KeyboardFocusLostEvent()
915 {
916   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusLostEvent" );
917
918   if( mImpl->mTextInput )
919   {
920     TextInput::Event event( TextInput::KEYBOARD_FOCUS_LOST_EVENT );
921     mImpl->mTextInput->mEventQueue.push_back( event );
922
923     RequestRelayout();
924   }
925 }
926
927 bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
928 {
929   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyEvent" );
930
931   if( mImpl->mTextInput )
932   {
933     TextInput::Event event( TextInput::KEY_EVENT );
934     event.p1.mInt = keyEvent.keyCode;
935     event.p2.mString = NULL;
936
937     const std::string& keyString = keyEvent.keyPressed;
938     if ( !keyString.empty() )
939     {
940       event.p2.mString = new char[keyString.size() + 1];
941       std::copy(keyString.begin(), keyString.end(), event.p2.mString);
942       event.p2.mString[keyString.size()] = '\0';
943     }
944
945     mImpl->mTextInput->mEventQueue.push_back( event );
946
947     RequestRelayout();
948   }
949
950   return false;
951 }
952
953 void Controller::TapEvent( unsigned int tapCount, float x, float y )
954 {
955   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected TapEvent" );
956
957   if( mImpl->mTextInput )
958   {
959     TextInput::Event event( TextInput::TAP_EVENT );
960     event.p1.mUint = tapCount;
961     event.p2.mFloat = x;
962     event.p3.mFloat = y;
963     mImpl->mTextInput->mEventQueue.push_back( event );
964
965     RequestRelayout();
966   }
967 }
968
969 void Controller::GrabHandleEvent( GrabHandleState state, float x, float y )
970 {
971   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected GrabHandleEvent" );
972
973   if( mImpl->mTextInput )
974   {
975     TextInput::Event event( TextInput::GRAB_HANDLE_EVENT );
976     event.p1.mUint  = state;
977     event.p2.mFloat = x;
978     event.p3.mFloat = y;
979     mImpl->mTextInput->mEventQueue.push_back( event );
980
981     RequestRelayout();
982   }
983 }
984
985 Controller::~Controller()
986 {
987   delete mImpl;
988 }
989
990 Controller::Controller( ControlInterface& controlInterface )
991 : mImpl( NULL )
992 {
993   mImpl = new Controller::Impl( controlInterface );
994 }
995
996 } // namespace Text
997
998 } // namespace Toolkit
999
1000 } // namespace Dali