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