Removed some pointless setters
[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::EnableTextInput( DecoratorPtr decorator )
557 {
558   if( !mImpl->mTextInput )
559   {
560     mImpl->mTextInput = new TextInput( mImpl->mLogicalModel, mImpl->mVisualModel, decorator );
561   }
562 }
563
564 bool Controller::Relayout( const Vector2& size )
565 {
566   if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
567   {
568     // Not worth to relayout if width or height is equal to zero.
569     return false;
570   }
571
572   if( size != mImpl->mControlSize )
573   {
574     // Operations that need to be done if the size changes.
575     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
576                                                              LAYOUT                    |
577                                                              UPDATE_ACTUAL_SIZE        |
578                                                              UPDATE_POSITIONS          |
579                                                              UPDATE_LINES              |
580                                                              REORDER );
581
582     mImpl->mControlSize = size;
583   }
584
585   Size layoutSize;
586   bool updated = DoRelayout( mImpl->mControlSize,
587                              mImpl->mOperationsPending,
588                              layoutSize );
589
590   // Do not re-do any operation until something changes.
591   mImpl->mOperationsPending = NO_OPERATION;
592
593   if( mImpl->mTextInput )
594   {
595     // Move the cursor, grab handle etc.
596     updated = mImpl->mTextInput->ProcessInputEvents() || updated;
597   }
598
599   return updated;
600 }
601
602 bool Controller::DoRelayout( const Vector2& size,
603                              OperationsMask operationsRequired,
604                              Size& layoutSize )
605 {
606   bool viewUpdated( false );
607
608   // Calculate the operations to be done.
609   const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
610
611   Vector<Character> utf32Characters;
612   Length characterCount = 0u;
613   if( CONVERT_TO_UTF32 & operations )
614   {
615     std::string& text = mImpl->mNewText;
616
617     //  Convert text into UTF-32
618     utf32Characters.Resize( text.size() );
619
620     // This is a bit horrible but std::string returns a (signed) char*
621     const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
622
623     // Transform a text array encoded in utf8 into an array encoded in utf32.
624     // It returns the actual number of characters.
625     characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() );
626     utf32Characters.Resize( characterCount );
627
628     // Sets the text into the model.
629     mImpl->mLogicalModel->SetText( utf32Characters.Begin(), characterCount );
630
631     // Discard temporary text
632     text.clear();
633   }
634
635   Vector<LineBreakInfo> lineBreakInfo;
636   if( GET_LINE_BREAKS & operations )
637   {
638     // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
639     // calculate the bidirectional info for each 'paragraph'.
640     // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
641     // is not shaped together).
642     lineBreakInfo.Resize( characterCount, TextAbstraction::LINE_NO_BREAK );
643
644     SetLineBreakInfo( utf32Characters,
645                       lineBreakInfo );
646
647     mImpl->mLogicalModel->SetLineBreakInfo( lineBreakInfo.Begin(), characterCount );
648   }
649
650   Vector<WordBreakInfo> wordBreakInfo;
651   if( GET_WORD_BREAKS & operations )
652   {
653     // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
654     wordBreakInfo.Resize( characterCount, TextAbstraction::WORD_NO_BREAK );
655
656     SetWordBreakInfo( utf32Characters,
657                       wordBreakInfo );
658
659     mImpl->mLogicalModel->SetWordBreakInfo( wordBreakInfo.Begin(), characterCount );
660   }
661
662   const bool getScripts = GET_SCRIPTS & operations;
663   const bool validateFonts = VALIDATE_FONTS & operations;
664
665   Vector<ScriptRun> scripts;
666   Vector<FontRun> fonts;
667
668   if( mImpl->mFontDefaults )
669   {
670     // TODO - pass into ValidateFonts
671   }
672
673   if( getScripts || validateFonts )
674   {
675     // Validates the fonts assigned by the application or assigns default ones.
676     // It makes sure all the characters are going to be rendered by the correct font.
677     MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
678
679     if( getScripts )
680     {
681       // Retrieves the scripts used in the text.
682       multilanguageSupport.SetScripts( utf32Characters,
683                                        lineBreakInfo,
684                                        scripts );
685
686       // Sets the scripts into the model.
687       mImpl->mLogicalModel->SetScripts( scripts.Begin(), scripts.Count() );
688     }
689
690     if( validateFonts )
691     {
692       // Validates the fonts. If there is a character with no assigned font it sets a default one.
693       // After this call, fonts are validated.
694       multilanguageSupport.ValidateFonts( utf32Characters,
695                                           scripts,
696                                           fonts );
697
698       // Sets the fonts into the model.
699       mImpl->mLogicalModel->SetFonts( fonts.Begin(), fonts.Count() );
700     }
701   }
702
703   Vector<BidirectionalParagraphInfoRun> bidirectionalInfo;
704   if( BIDI_INFO & operations )
705   {
706     // Some vectors with data needed to get the paragraph's bidirectional info may be void
707     // after the first time the text has been laid out.
708     // Fill the vectors again.
709
710     const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
711
712     if( 0u == utf32Characters.Count() )
713     {
714       utf32Characters.Resize( numberOfCharacters );
715
716       mImpl->mLogicalModel->GetText( utf32Characters.Begin(),
717                                      0u,
718                                      numberOfCharacters );
719     }
720
721     if( 0u == lineBreakInfo.Count() )
722     {
723       lineBreakInfo.Resize( numberOfCharacters );
724
725       mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(),
726                                               0u,
727                                               numberOfCharacters );
728     }
729
730     if( 0u == scripts.Count() )
731     {
732       scripts.Resize( mImpl->mLogicalModel->GetNumberOfScriptRuns( 0u,
733                                                                    numberOfCharacters ) );
734       mImpl->mLogicalModel->GetScriptRuns( scripts.Begin(),
735                                            0u,
736                                            numberOfCharacters );
737     }
738
739     // Count the number of LINE_NO_BREAK to reserve some space for the vector of paragraph's
740     // bidirectional info.
741
742     Length numberOfParagraphs = 0u;
743
744     const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
745     for( Length index = 0u; index < characterCount; ++index )
746     {
747       if( TextAbstraction::LINE_NO_BREAK == *( lineBreakInfoBuffer + index ) )
748       {
749         ++numberOfParagraphs;
750       }
751     }
752
753     bidirectionalInfo.Reserve( numberOfParagraphs );
754
755     // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
756     SetBidirectionalInfo( utf32Characters,
757                           scripts,
758                           lineBreakInfo,
759                           bidirectionalInfo );
760
761     mImpl->mLogicalModel->SetBidirectionalInfo( bidirectionalInfo.Begin(),
762                                                 bidirectionalInfo.Count() );
763   }
764
765   Vector<GlyphInfo> glyphs;
766   Vector<CharacterIndex> glyphsToCharactersMap;
767   Vector<Length> charactersPerGlyph;
768   if( SHAPE_TEXT & operations )
769   {
770     // Shapes the text.
771     ShapeText( utf32Characters,
772                lineBreakInfo,
773                scripts,
774                fonts,
775                glyphs,
776                glyphsToCharactersMap,
777                charactersPerGlyph );
778   }
779
780   if( GET_GLYPH_METRICS & operations )
781   {
782     mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), glyphs.Count() );
783   }
784
785   Length numberOfGlyphs = glyphs.Count();
786   if( 0u != numberOfGlyphs )
787   {
788     // Sets the glyphs into the model.
789     mImpl->mVisualModel->SetGlyphs( glyphs.Begin(),
790                                     glyphsToCharactersMap.Begin(),
791                                     charactersPerGlyph.Begin(),
792                                     numberOfGlyphs );
793   }
794
795   if( LAYOUT & operations )
796   {
797     // Some vectors with data needed to layout and reorder may be void
798     // after the first time the text has been laid out.
799     // Fill the vectors again.
800
801     const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
802     numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
803
804     if( 0u == lineBreakInfo.Count() )
805     {
806       lineBreakInfo.Resize( numberOfCharacters );
807       mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(),
808                                               0u,
809                                               numberOfCharacters );
810     }
811
812     if( 0u == wordBreakInfo.Count() )
813     {
814       wordBreakInfo.Resize( numberOfCharacters );
815       mImpl->mLogicalModel->GetWordBreakInfo( wordBreakInfo.Begin(),
816                                               0u,
817                                               numberOfCharacters );
818     }
819
820     if( 0u == glyphs.Count() )
821     {
822       glyphs.Resize( numberOfGlyphs );
823       mImpl->mVisualModel->GetGlyphs( glyphs.Begin(),
824                                       0u,
825                                       numberOfGlyphs );
826     }
827
828     if( 0u == glyphsToCharactersMap.Count() )
829     {
830       glyphsToCharactersMap.Resize( numberOfGlyphs );
831       mImpl->mVisualModel->GetGlyphToCharacterMap( glyphsToCharactersMap.Begin(),
832                                                    0u,
833                                                    numberOfGlyphs );
834     }
835
836     if( 0u == charactersPerGlyph.Count() )
837     {
838       charactersPerGlyph.Resize( numberOfGlyphs );
839       mImpl->mVisualModel->GetCharactersPerGlyphMap( charactersPerGlyph.Begin(),
840                                                      0u,
841                                                      numberOfGlyphs );
842     }
843
844     // Set the layout parameters.
845     LayoutParameters layoutParameters( size,
846                                        lineBreakInfo.Begin(),
847                                        wordBreakInfo.Begin(),
848                                        numberOfGlyphs,
849                                        glyphs.Begin(),
850                                        glyphsToCharactersMap.Begin(),
851                                        charactersPerGlyph.Begin() );
852
853     // Reserve space to set the positions of the glyphs.
854     Vector<Vector2> glyphPositions;
855     glyphPositions.Resize( numberOfGlyphs );
856
857     // The laid-out lines.
858     // It's not possible to know in how many lines the text is going to be laid-out,
859     // but it can be resized at least with the number of 'paragraphs' to avoid
860     // some re-allocations.
861     Vector<LineRun> lines;
862     lines.Reserve( mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters ) );
863
864     // Update the visual model.
865     viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters,
866                                                    glyphPositions,
867                                                    lines,
868                                                    layoutSize );
869
870     if( viewUpdated )
871     {
872       // Reorder the lines
873       if( REORDER & operations )
874       {
875         const Length numberOfBidiParagraphs = mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters );
876
877         if( 0u == bidirectionalInfo.Count() )
878         {
879           bidirectionalInfo.Resize( numberOfBidiParagraphs );
880           mImpl->mLogicalModel->GetBidirectionalInfo( bidirectionalInfo.Begin(),
881                                                       0u,
882                                                       numberOfCharacters );
883         }
884
885         // Check first if there are paragraphs with bidirectional info.
886         if( 0u != bidirectionalInfo.Count() )
887         {
888           // Get the lines
889           const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines();
890
891           // Reorder the lines.
892           Vector<BidirectionalLineInfoRun> lineBidirectionalInfoRuns;
893           lineBidirectionalInfoRuns.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
894           ReorderLines( bidirectionalInfo,
895                         lines,
896                         lineBidirectionalInfoRuns );
897
898           // Set the bidirectional info into the model.
899           const Length numberOfBidirectionalInfoRuns = lineBidirectionalInfoRuns.Count();
900           mImpl->mLogicalModel->SetVisualToLogicalMap( lineBidirectionalInfoRuns.Begin(),
901                                                        numberOfBidirectionalInfoRuns );
902
903           // Set the bidirectional info per line into the layout parameters.
904           layoutParameters.lineBidirectionalInfoRunsBuffer = lineBidirectionalInfoRuns.Begin();
905           layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns;
906
907           // Get the character to glyph conversion table and set into the layout.
908           Vector<GlyphIndex> characterToGlyphMap;
909           characterToGlyphMap.Resize( numberOfCharacters );
910
911           layoutParameters.charactersToGlyphsBuffer = characterToGlyphMap.Begin();
912           mImpl->mVisualModel->GetCharacterToGlyphMap( layoutParameters.charactersToGlyphsBuffer,
913                                                        0u,
914                                                        numberOfCharacters );
915
916           // Get the glyphs per character table and set into the layout.
917           Vector<Length> glyphsPerCharacter;
918           glyphsPerCharacter.Resize( numberOfCharacters );
919
920           layoutParameters.glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
921           mImpl->mVisualModel->GetGlyphsPerCharacterMap( layoutParameters.glyphsPerCharacterBuffer,
922                                                          0u,
923                                                          numberOfCharacters );
924
925           // Re-layout the text. Reorder those lines with right to left characters.
926           mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters,
927                                                          glyphPositions );
928
929           // Free the allocated memory used to store the conversion table in the bidirectional line info run.
930           for( Vector<BidirectionalLineInfoRun>::Iterator it = lineBidirectionalInfoRuns.Begin(),
931                  endIt = lineBidirectionalInfoRuns.End();
932                it != endIt;
933                ++it )
934           {
935             BidirectionalLineInfoRun& bidiLineInfo = *it;
936
937             free( bidiLineInfo.visualToLogicalMap );
938           }
939         }
940       }
941
942       // Sets the positions into the model.
943       if( UPDATE_POSITIONS & operations )
944       {
945         mImpl->mVisualModel->SetGlyphPositions( glyphPositions.Begin(),
946                                                 numberOfGlyphs );
947       }
948
949       // Sets the lines into the model.
950       if( UPDATE_LINES & operations )
951       {
952         mImpl->mVisualModel->SetLines( lines.Begin(),
953                                        lines.Count() );
954       }
955
956       // Sets the actual size.
957       if( UPDATE_ACTUAL_SIZE & operations )
958       {
959         mImpl->mVisualModel->SetActualSize( layoutSize );
960       }
961     }
962   }
963   else
964   {
965     layoutSize = mImpl->mVisualModel->GetActualSize();
966   }
967
968   return viewUpdated;
969 }
970
971 Vector3 Controller::GetNaturalSize()
972 {
973   Vector3 naturalSize;
974
975   if( mImpl->mRecalculateNaturalSize )
976   {
977     // Operations that can be done only once until the text changes.
978     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
979                                                                            GET_SCRIPTS       |
980                                                                            VALIDATE_FONTS    |
981                                                                            GET_LINE_BREAKS   |
982                                                                            GET_WORD_BREAKS   |
983                                                                            SHAPE_TEXT        |
984                                                                            GET_GLYPH_METRICS );
985
986     // Operations that need to be done if the size changes.
987     const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
988                                                                         REORDER );
989
990     DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
991                 static_cast<OperationsMask>( onlyOnceOperations |
992                                              sizeOperations ),
993                 naturalSize.GetVectorXY() );
994
995     // Do not do again the only once operations.
996     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
997
998     // Do the size related operations again.
999     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
1000
1001     // Stores the natural size to avoid recalculate it again
1002     // unless the text/style changes.
1003     mImpl->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() );
1004
1005     mImpl->mRecalculateNaturalSize = false;
1006   }
1007   else
1008   {
1009     naturalSize = mImpl->mVisualModel->GetNaturalSize();
1010   }
1011
1012   return naturalSize;
1013 }
1014
1015 float Controller::GetHeightForWidth( float width )
1016 {
1017   Size layoutSize;
1018   if( width != mImpl->mControlSize.width )
1019   {
1020     // Operations that can be done only once until the text changes.
1021     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
1022                                                                            GET_SCRIPTS       |
1023                                                                            VALIDATE_FONTS    |
1024                                                                            GET_LINE_BREAKS   |
1025                                                                            GET_WORD_BREAKS   |
1026                                                                            SHAPE_TEXT        |
1027                                                                            GET_GLYPH_METRICS );
1028
1029     // Operations that need to be done if the size changes.
1030     const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
1031                                                                         REORDER );
1032
1033     DoRelayout( Size( width, MAX_FLOAT ),
1034                 static_cast<OperationsMask>( onlyOnceOperations |
1035                                              sizeOperations ),
1036                 layoutSize );
1037
1038     // Do not do again the only once operations.
1039     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
1040
1041     // Do the size related operations again.
1042     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
1043   }
1044   else
1045   {
1046     layoutSize = mImpl->mVisualModel->GetActualSize();
1047   }
1048
1049   return layoutSize.height;
1050 }
1051
1052 View& Controller::GetView()
1053 {
1054   return mImpl->mView;
1055 }
1056
1057 LayoutEngine& Controller::GetLayoutEngine()
1058 {
1059   return mImpl->mLayoutEngine;
1060 }
1061
1062 void Controller::RequestRelayout()
1063 {
1064   mImpl->mControlInterface.RequestTextRelayout();
1065 }
1066
1067 void Controller::KeyboardFocusGainEvent()
1068 {
1069   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusGainEvent" );
1070
1071   if( mImpl->mTextInput )
1072   {
1073     TextInput::Event event( TextInput::KEYBOARD_FOCUS_GAIN_EVENT );
1074     mImpl->mTextInput->mEventQueue.push_back( event );
1075
1076     RequestRelayout();
1077   }
1078 }
1079
1080 void Controller::KeyboardFocusLostEvent()
1081 {
1082   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusLostEvent" );
1083
1084   if( mImpl->mTextInput )
1085   {
1086     TextInput::Event event( TextInput::KEYBOARD_FOCUS_LOST_EVENT );
1087     mImpl->mTextInput->mEventQueue.push_back( event );
1088
1089     RequestRelayout();
1090   }
1091 }
1092
1093 bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
1094 {
1095   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyEvent" );
1096
1097   if( mImpl->mTextInput )
1098   {
1099     TextInput::Event event( TextInput::KEY_EVENT );
1100     event.p1.mInt = keyEvent.keyCode;
1101     event.p2.mString = NULL;
1102
1103     const std::string& keyString = keyEvent.keyPressed;
1104     if ( !keyString.empty() )
1105     {
1106       event.p2.mString = new char[keyString.size() + 1];
1107       std::copy(keyString.begin(), keyString.end(), event.p2.mString);
1108       event.p2.mString[keyString.size()] = '\0';
1109     }
1110
1111     mImpl->mTextInput->mEventQueue.push_back( event );
1112
1113     RequestRelayout();
1114   }
1115
1116   return false;
1117 }
1118
1119 void Controller::TapEvent( unsigned int tapCount, float x, float y )
1120 {
1121   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected TapEvent" );
1122
1123   if( mImpl->mTextInput )
1124   {
1125     TextInput::Event event( TextInput::TAP_EVENT );
1126     event.p1.mUint = tapCount;
1127     event.p2.mFloat = x;
1128     event.p3.mFloat = y;
1129     mImpl->mTextInput->mEventQueue.push_back( event );
1130
1131     RequestRelayout();
1132   }
1133 }
1134
1135 void Controller::GrabHandleEvent( GrabHandleState state, float x, float y )
1136 {
1137   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected GrabHandleEvent" );
1138
1139   if( mImpl->mTextInput )
1140   {
1141     TextInput::Event event( TextInput::GRAB_HANDLE_EVENT );
1142     event.p1.mUint  = state;
1143     event.p2.mFloat = x;
1144     event.p3.mFloat = y;
1145     mImpl->mTextInput->mEventQueue.push_back( event );
1146
1147     RequestRelayout();
1148   }
1149 }
1150
1151 Controller::~Controller()
1152 {
1153   delete mImpl;
1154 }
1155
1156 Controller::Controller( ControlInterface& controlInterface )
1157 : mImpl( NULL )
1158 {
1159   mImpl = new Controller::Impl( controlInterface );
1160 }
1161
1162 } // namespace Text
1163
1164 } // namespace Toolkit
1165
1166 } // namespace Dali