Merge "Added code for stylable transitions" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / text / text-visual.cpp
1 /*
2  * Copyright (c) 2016 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/visuals/text/text-visual.h>
20
21 // EXTERNAL HEADER
22 #include <dali/devel-api/scripting/enum-helper.h>
23 // #include <dali/devel-api/scripting/scripting.h>
24
25 // INTERNAL HEADER
26 #include <dali-toolkit/public-api/text/rendering-backend.h>
27 #include <dali-toolkit/public-api/visuals/text-visual-properties.h>
28 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
29 #include <dali-toolkit/internal/text/rendering/text-backend.h>
30 #include <dali-toolkit/internal/text/text-view.h>
31 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
32 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
33 #include <dali-toolkit/internal/text/text-font-style.h>
34 #include <dali-toolkit/internal/text/text-effects-style.h>
35
36 using Dali::Toolkit::Text::LayoutEngine;
37
38 namespace Dali
39 {
40
41 namespace Toolkit
42 {
43
44 namespace Internal
45 {
46
47 namespace
48 {
49
50 // Property names.
51 const char * const RENDERING_BACKEND_PROPERTY( "renderingBackend" );
52 const char * const TEXT_PROPERTY( "text" );
53 const char * const FONT_FAMILY_PROPERTY( "fontFamily" );
54 const char * const FONT_STYLE_PROPERTY( "fontStyle" );
55 const char * const POINT_SIZE_PROPERTY( "pointSize" );
56 const char * const MULTI_LINE_PROPERTY( "multiLine" );
57 const char * const HORIZONTAL_ALIGNMENT_PROPERTY( "horizontalAlignment" );
58 const char * const VERTICAL_ALIGNMENT_PROPERTY( "verticalAlignment" );
59 const char * const TEXT_COLOR_PROPERTY( "textColor" );
60 const char * const ENABLE_MARKUP_PROPERTY( "enableMarkup" );
61 const char * const ENABLE_AUTO_SCROLL_PROPERTY( "enableAutoScroll" );
62 const char * const AUTO_SCROLL_SPEED_PROPERTY( "autoScrollSpeed" );
63 const char * const AUTO_SCROLL_LOOP_COUNT_PROPERTY( "autoScrollLoopCount" );
64 const char * const AUTO_SCROLL_GAP_PROPERTY( "autoScrollGap" );
65 const char * const LINE_SPACING_PROPERTY( "lineSpacing" );
66 const char * const UNDERLINE_PROPERTY( "underline" );
67 const char * const SHADOW_PROPERTY( "shadow" );
68 const char * const OUTLINE_PROPERTY( "outline" );
69 const char * const BATCHING_ENABLED_PROPERTY( "batchingEnabled" );
70
71 const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
72 {
73   { "BEGIN",  Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN  },
74   { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER },
75   { "END",    Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END    },
76 };
77 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
78
79 const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
80 {
81   { "TOP",    Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP    },
82   { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER },
83   { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM },
84 };
85 const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] );
86
87 std::string GetHorizontalAlignment( LayoutEngine::HorizontalAlignment alignment )
88 {
89   const char* name = Scripting::GetEnumerationName<Toolkit::Text::LayoutEngine::HorizontalAlignment>( alignment,
90                                                                                                       HORIZONTAL_ALIGNMENT_STRING_TABLE,
91                                                                                                       HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
92
93   return std::string( name );
94 }
95
96 std::string GetVerticalAlignment( LayoutEngine::VerticalAlignment alignment )
97 {
98   const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( alignment,
99                                                                                                       VERTICAL_ALIGNMENT_STRING_TABLE,
100                                                                                                       VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
101
102   return std::string( name );
103 }
104
105 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
106   attribute mediump vec2 aPosition;\n
107   uniform mediump mat4 uMvpMatrix;\n
108   uniform mediump vec3 uSize;\n
109   uniform mediump vec4 pixelArea;
110   varying mediump vec2 vTexCoord;\n
111   \n
112   void main()\n
113   {\n
114     mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
115     vertexPosition.xyz *= uSize;\n
116     vertexPosition = uMvpMatrix * vertexPosition;\n
117     \n
118     vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );\n
119     gl_Position = vertexPosition;\n
120   }\n
121 );
122
123 const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER(
124     varying mediump vec2 vTexCoord;\n
125     uniform sampler2D sTexture;\n
126     uniform mediump vec4 uAtlasRect;\n
127     uniform lowp vec4 uColor;\n
128     \n
129     void main()\n
130     {\n
131       mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n
132       gl_FragColor = texture2D( sTexture, texCoord ) * uColor;\n
133     }\n
134 );
135
136 Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridSize )
137 {
138   Geometry geometry;
139
140   if( gridSize == ImageDimensions( 1, 1 ) )
141   {
142     geometry = factoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
143     if( !geometry )
144     {
145       geometry =  VisualFactoryCache::CreateQuadGeometry();
146       factoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY, geometry );
147     }
148   }
149   else
150   {
151     geometry = VisualFactoryCache::CreateGridGeometry( gridSize );
152   }
153
154   return geometry;
155 }
156
157 } // unnamed namespace
158
159 TextVisualPtr TextVisual::New( VisualFactoryCache& factoryCache )
160 {
161   return new TextVisual( factoryCache );
162 }
163
164 void TextVisual::SetTextControlInterface( Text::ControlInterface* controlInterface )
165 {
166   if( mController )
167   {
168     mController->SetTextControlInterface( controlInterface );
169   }
170 }
171
172 void TextVisual::SetSize( const Vector2& size )
173 {
174   const Text::Controller::UpdateTextType updateTextType = mController->Relayout( size );
175
176   if( ( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) ) ||
177       !mRenderer )
178   {
179     if( !mRenderer )
180     {
181       mRenderer = Text::Backend::Get().NewRenderer( mRenderingBackend );
182     }
183
184     RenderText();
185   }
186 }
187
188 float TextVisual::GetHeightForWidth( float width ) const
189 {
190   return mController->GetHeightForWidth( width );
191 }
192
193 void TextVisual::GetNaturalSize( Vector2& naturalSize ) const
194 {
195   naturalSize = mController->GetNaturalSize().GetVectorXY();
196 }
197
198 void TextVisual::DoCreatePropertyMap( Property::Map& map ) const
199 {
200   Property::Value value;
201
202   map.Clear();
203   map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::TEXT );
204
205   map.Insert( Toolkit::TextVisual::Property::RENDERING_BACKEND, mRenderingBackend );
206
207   std::string text;
208   mController->GetText( text );
209   map.Insert( Toolkit::TextVisual::Property::TEXT, text );
210
211   map.Insert( Toolkit::TextVisual::Property::FONT_FAMILY, mController->GetDefaultFontFamily() );
212
213   GetFontStyleProperty( mController, value, Text::FontStyle::DEFAULT );
214   map.Insert( Toolkit::TextVisual::Property::FONT_STYLE, value );
215
216   map.Insert( Toolkit::TextVisual::Property::POINT_SIZE, mController->GetDefaultPointSize() );
217
218   map.Insert( Toolkit::TextVisual::Property::MULTI_LINE, mController->IsMultiLineEnabled() );
219
220   map.Insert( Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT, GetHorizontalAlignment( mController->GetHorizontalAlignment() ) );
221
222   map.Insert( Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT, GetVerticalAlignment( mController->GetVerticalAlignment() ) );
223
224   map.Insert( Toolkit::TextVisual::Property::TEXT_COLOR, mController->GetTextColor() );
225
226   map.Insert( Toolkit::TextVisual::Property::ENABLE_MARKUP, mController->IsMarkupProcessorEnabled() );
227
228   map.Insert( Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL, mController->IsAutoScrollEnabled() );
229
230   map.Insert( Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED, mController->GetAutoScrollSpeed() );
231
232   map.Insert( Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT, mController->GetAutoScrollLoopCount() );
233
234   map.Insert( Toolkit::TextVisual::Property::AUTO_SCROLL_GAP, mController->GetAutoScrollWrapGap() );
235
236   map.Insert( Toolkit::TextVisual::Property::LINE_SPACING, mController->GetDefaultLineSpacing() );
237
238   GetUnderlineProperties( mController, value, Text::EffectStyle::DEFAULT );
239   map.Insert( Toolkit::TextVisual::Property::UNDERLINE, value );
240
241   GetShadowProperties( mController, value, Text::EffectStyle::DEFAULT );
242   map.Insert( Toolkit::TextVisual::Property::SHADOW, value );
243
244   GetOutlineProperties( mController, value, Text::EffectStyle::DEFAULT );
245   map.Insert( Toolkit::TextVisual::Property::OUTLINE, value );
246
247   map.Insert( Toolkit::TextVisual::Property::BATCHING_ENABLED, false ); // TODO
248 }
249
250 TextVisual::TextVisual( VisualFactoryCache& factoryCache )
251 : Visual::Base( factoryCache ),
252   mController( Text::Controller::New() ),
253   mRenderingBackend( Toolkit::Text::DEFAULT_RENDERING_BACKEND ),
254   mHasBeenStaged( false )
255 {
256 }
257
258 TextVisual::~TextVisual()
259 {
260 }
261
262 void TextVisual::DoInitialize( Actor& actor, const Property::Map& propertyMap )
263 {
264   mSelf = actor;
265
266   for( Property::Map::SizeType index = 0u, count = propertyMap.Count(); index < count; ++index )
267   {
268     const KeyValuePair& keyValue = propertyMap.GetKeyValue( index );
269
270     switch( keyValue.first.type )
271     {
272       case Property::Key::INDEX:
273       {
274         if( Toolkit::Visual::Property::TYPE != keyValue.first.indexKey ) // Toolkit::Visual::Property::TYPE is not a TextVisual's property.
275         {
276           DoSetProperty( keyValue.first.indexKey, keyValue.second );
277         }
278         break;
279       }
280       case Property::Key::STRING:
281       {
282         if( keyValue.first.stringKey == RENDERING_BACKEND_PROPERTY )
283         {
284           DoSetProperty( Toolkit::TextVisual::Property::RENDERING_BACKEND, keyValue.second );
285         }
286         else if( keyValue.first.stringKey == TEXT_PROPERTY )
287         {
288           DoSetProperty( Toolkit::TextVisual::Property::TEXT, keyValue.second );
289         }
290         else if( keyValue.first.stringKey == FONT_FAMILY_PROPERTY )
291         {
292           DoSetProperty( Toolkit::TextVisual::Property::FONT_FAMILY, keyValue.second );
293         }
294         else if( keyValue.first.stringKey == FONT_STYLE_PROPERTY )
295         {
296           DoSetProperty( Toolkit::TextVisual::Property::FONT_STYLE, keyValue.second );
297         }
298         else if( keyValue.first.stringKey == POINT_SIZE_PROPERTY )
299         {
300           DoSetProperty( Toolkit::TextVisual::Property::POINT_SIZE, keyValue.second );
301         }
302         else if( keyValue.first.stringKey == MULTI_LINE_PROPERTY )
303         {
304           DoSetProperty( Toolkit::TextVisual::Property::MULTI_LINE, keyValue.second );
305         }
306         else if( keyValue.first.stringKey == HORIZONTAL_ALIGNMENT_PROPERTY )
307         {
308           DoSetProperty( Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT, keyValue.second );
309         }
310         else if( keyValue.first.stringKey == VERTICAL_ALIGNMENT_PROPERTY )
311         {
312           DoSetProperty( Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT, keyValue.second );
313         }
314         else if( keyValue.first.stringKey == TEXT_COLOR_PROPERTY )
315         {
316           DoSetProperty( Toolkit::TextVisual::Property::TEXT_COLOR, keyValue.second );
317         }
318         else if( keyValue.first.stringKey == ENABLE_MARKUP_PROPERTY )
319         {
320           DoSetProperty( Toolkit::TextVisual::Property::ENABLE_MARKUP, keyValue.second );
321         }
322         else if( keyValue.first.stringKey == ENABLE_AUTO_SCROLL_PROPERTY )
323         {
324           DoSetProperty( Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL, keyValue.second );
325         }
326         else if( keyValue.first.stringKey == AUTO_SCROLL_SPEED_PROPERTY )
327         {
328           DoSetProperty( Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED, keyValue.second );
329         }
330         else if( keyValue.first.stringKey == AUTO_SCROLL_LOOP_COUNT_PROPERTY )
331         {
332           DoSetProperty( Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT, keyValue.second );
333         }
334         else if( keyValue.first.stringKey == AUTO_SCROLL_GAP_PROPERTY )
335         {
336           DoSetProperty( Toolkit::TextVisual::Property::AUTO_SCROLL_GAP, keyValue.second );
337         }
338         else if( keyValue.first.stringKey == LINE_SPACING_PROPERTY )
339         {
340           DoSetProperty( Toolkit::TextVisual::Property::LINE_SPACING, keyValue.second );
341         }
342         else if( keyValue.first.stringKey == UNDERLINE_PROPERTY )
343         {
344           DoSetProperty( Toolkit::TextVisual::Property::UNDERLINE, keyValue.second );
345         }
346         else if( keyValue.first.stringKey == SHADOW_PROPERTY )
347         {
348           DoSetProperty( Toolkit::TextVisual::Property::SHADOW, keyValue.second );
349         }
350         else if( keyValue.first.stringKey == OUTLINE_PROPERTY )
351         {
352           DoSetProperty( Toolkit::TextVisual::Property::OUTLINE, keyValue.second );
353         }
354         else if( keyValue.first.stringKey == BATCHING_ENABLED_PROPERTY )
355         {
356           DoSetProperty( Toolkit::TextVisual::Property::BATCHING_ENABLED, keyValue.second );
357         }
358         break;
359       }
360     }
361   }
362
363   // Retrieve the layout engine to set whether to elide the text and set the cursor's width.
364   Text::LayoutEngine& engine = mController->GetLayoutEngine();
365
366   // Elide the text if it exceeds the boundaries.
367   engine.SetTextEllipsisEnabled( true );
368
369   // Sets 0 as cursor's width.
370   engine.SetCursorWidth( 0u ); // Do not layout space for the cursor.
371 }
372
373 void TextVisual::DoSetOnStage( Actor& actor )
374 {
375   // TODO Create the actual renderer(s) for the text!!!!
376   //      Will crash if no mImpl->mRenderer is set.
377   Geometry geometry;
378   Shader shader;
379
380   geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
381
382   shader = mFactoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP );
383   if( !shader )
384   {
385     shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP );
386     mFactoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader );
387   }
388
389   mImpl->mRenderer = Renderer::New( geometry, shader );
390
391   mSelf = actor;
392
393   if( mHasBeenStaged )
394   {
395     RenderText();
396   }
397   else
398   {
399     mHasBeenStaged = true;
400   }
401 }
402
403 void TextVisual::DoSetOffStage( Actor& actor )
404 {
405   mSelf.Reset();
406 }
407
408 void TextVisual::DoSetProperty( Dali::Property::Index index, const Dali::Property::Value& propertyValue )
409 {
410   switch( index )
411   {
412     case Toolkit::TextVisual::Property::RENDERING_BACKEND:
413     {
414       int backend = propertyValue.Get<int>();
415
416 #ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING
417       if( Text::RENDERING_VECTOR_BASED == backend )
418       {
419         backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering
420       }
421 #endif
422       if( mRenderingBackend != backend )
423       {
424         mRenderingBackend = backend;
425         mRenderer.Reset();
426
427         // When using the vector-based rendering, the size of the GLyphs are different
428         TextAbstraction::GlyphType glyphType = ( Text::RENDERING_VECTOR_BASED == mRenderingBackend ) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH;
429         mController->SetGlyphType( glyphType );
430       }
431       break;
432     }
433     case Toolkit::TextVisual::Property::TEXT:
434     {
435       mController->SetText( propertyValue.Get<std::string>() );
436       break;
437     }
438     case Toolkit::TextVisual::Property::FONT_FAMILY:
439     {
440       SetFontFamilyProperty( mController, propertyValue );
441       break;
442     }
443     case Toolkit::TextVisual::Property::FONT_STYLE:
444     {
445       SetFontStyleProperty( mController, propertyValue, Text::FontStyle::DEFAULT );
446       break;
447     }
448     case Toolkit::TextVisual::Property::POINT_SIZE:
449     {
450       const float pointSize = propertyValue.Get<float>();
451
452       if( !Equals( mController->GetDefaultPointSize(), pointSize ) )
453       {
454         mController->SetDefaultPointSize( pointSize );
455       }
456       break;
457     }
458     case Toolkit::TextVisual::Property::MULTI_LINE:
459     {
460       mController->SetMultiLineEnabled( propertyValue.Get<bool>() );
461       break;
462     }
463     case Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT:
464     {
465       LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN );
466       if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( propertyValue.Get< std::string >().c_str(),
467                                                                                          HORIZONTAL_ALIGNMENT_STRING_TABLE,
468                                                                                          HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
469                                                                                          alignment ) )
470       {
471         mController->SetHorizontalAlignment( alignment );
472       }
473       break;
474     }
475     case Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT:
476     {
477       LayoutEngine::VerticalAlignment alignment( LayoutEngine::VERTICAL_ALIGN_BOTTOM );
478       if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( propertyValue.Get< std::string >().c_str(),
479                                                                                        VERTICAL_ALIGNMENT_STRING_TABLE,
480                                                                                        VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
481                                                                                        alignment ) )
482       {
483         mController->SetVerticalAlignment( alignment );
484       }
485       break;
486     }
487     case Toolkit::TextVisual::Property::TEXT_COLOR:
488     {
489       const Vector4 textColor = propertyValue.Get< Vector4 >();
490       if( mController->GetTextColor() != textColor )
491       {
492         mController->SetTextColor( textColor );
493         mRenderer.Reset();
494       }
495       break;
496     }
497     case Toolkit::TextVisual::Property::ENABLE_MARKUP:
498     {
499       const bool enableMarkup = propertyValue.Get<bool>();
500       mController->SetMarkupProcessorEnabled( enableMarkup );
501       break;
502     }
503     case Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL:
504     {
505       const bool enableAutoScroll = propertyValue.Get<bool>();
506
507       // If request to auto scroll is the same as current state then do nothing.
508       if( enableAutoScroll != mController->IsAutoScrollEnabled() )
509       {
510         // If request is disable (false) and auto scrolling is enabled then need to stop it
511         if( !enableAutoScroll )
512         {
513           StopTextAutoScrolling(); // Causes the current animation to finish playing.
514         }
515         // If request is enable (true) then start autoscroll as not already running
516         else
517         {
518           mController->GetLayoutEngine().SetTextEllipsisEnabled( false );
519           mController->SetAutoScrollEnabled( enableAutoScroll );
520           mController->RequestRelayout();
521         }
522       }
523       break;
524     }
525     case Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED:
526     {
527       mController->SetAutoscrollSpeed( propertyValue.Get<int>() );
528       break;
529     }
530     case Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT:
531     {
532       const int loopCount = propertyValue.Get<int>();
533       if( loopCount > 0 )
534       {
535         mController->SetAutoScrollLoopCount( loopCount );
536       }
537       else
538       {
539         StopTextAutoScrolling(); // Causes the current animation to finish playing.
540       }
541       break;
542     }
543     case Toolkit::TextVisual::Property::AUTO_SCROLL_GAP:
544     {
545       mController->SetAutoScrollWrapGap( propertyValue.Get<float>() );
546       break;
547     }
548     case Toolkit::TextVisual::Property::LINE_SPACING:
549     {
550       const float lineSpacing = propertyValue.Get<float>();
551       mController->SetDefaultLineSpacing( lineSpacing );
552       mRenderer.Reset();
553       break;
554     }
555     case Toolkit::TextVisual::Property::UNDERLINE:
556     {
557       // TODO : This switch can be removed when the deprecated SHADOW_OFFSET and SHADOW_COLOR properties are finally removed.
558       //        Only the code for the STRING case should be kept.
559       switch( propertyValue.GetType() )
560       {
561         case Property::VECTOR4:
562         {
563           const Vector4 color = propertyValue.Get<Vector4>();
564           if( mController->GetUnderlineColor() != color )
565           {
566             mController->SetUnderlineColor( color );
567             mRenderer.Reset();
568           }
569           break;
570         }
571         case Property::FLOAT:
572         {
573           float height = propertyValue.Get<float>();
574           if( fabsf( mController->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 )
575           {
576             mController->SetUnderlineHeight( height );
577             mRenderer.Reset();
578           }
579           break;
580         }
581         case Property::BOOLEAN:
582         {
583           const bool enabled = propertyValue.Get<bool>();
584           if( mController->IsUnderlineEnabled() != enabled )
585           {
586             mController->SetUnderlineEnabled( enabled );
587             mRenderer.Reset();
588           }
589           break;
590         }
591         case Property::STRING:
592         {
593           const bool update = SetUnderlineProperties( mController, propertyValue, Text::EffectStyle::DEFAULT );
594           if( update )
595           {
596             mRenderer.Reset();
597           }
598           break;
599         }
600         default:
601         {
602           // Nothing to do.
603           break;
604         }
605       }
606
607       break;
608     }
609     case Toolkit::TextVisual::Property::SHADOW:
610     {
611       // TODO : This switch can be removed when the deprecated SHADOW_OFFSET and SHADOW_COLOR properties are finally removed.
612       //        Only the code for the STRING case should be kept.
613       switch( propertyValue.GetType() )
614       {
615         case Property::VECTOR2:
616         {
617           const Vector2 shadowOffset = propertyValue.Get<Vector2>();
618           if( mController->GetShadowOffset() != shadowOffset )
619           {
620             mController->SetShadowOffset( shadowOffset );
621             mRenderer.Reset();
622           }
623           break;
624         }
625         case Property::VECTOR4:
626         {
627           const Vector4 shadowColor = propertyValue.Get<Vector4>();
628           if( mController->GetShadowColor() != shadowColor )
629           {
630             mController->SetShadowColor( shadowColor );
631             mRenderer.Reset();
632           }
633           break;
634         }
635         case Property::STRING:
636         {
637           const bool update = SetShadowProperties( mController, propertyValue, Text::EffectStyle::DEFAULT );
638           if( update )
639           {
640             mRenderer.Reset();
641           }
642           break;
643         }
644         default:
645         {
646           // Nothing to do.
647           break;
648         }
649       }
650       break;
651     }
652     case Toolkit::TextVisual::Property::EMBOSS:
653     {
654       const bool update = SetEmbossProperties( mController, propertyValue, Text::EffectStyle::DEFAULT );
655       if( update )
656       {
657         mRenderer.Reset();
658      }
659       break;
660     }
661     case Toolkit::TextVisual::Property::OUTLINE:
662     {
663       const bool update = SetOutlineProperties( mController, propertyValue, Text::EffectStyle::DEFAULT );
664       if( update )
665       {
666         mRenderer.Reset();
667       }
668       break;
669     }
670     case Toolkit::TextVisual::Property::BATCHING_ENABLED:
671     {
672       // TODO
673       break;
674     }
675     default:
676     {
677       // Should not arrive here.
678       DALI_ASSERT_DEBUG( false );
679     }
680   }
681 }
682
683 Dali::Property::Value TextVisual::DoGetProperty( Dali::Property::Index index )
684 {
685   Dali::Property::Value value;
686
687   switch( index )
688   {
689     case Toolkit::TextVisual::Property::RENDERING_BACKEND:
690     {
691       value = mRenderingBackend;
692       break;
693     }
694     case Toolkit::TextVisual::Property::TEXT:
695     {
696       std::string text;
697       mController->GetText( text );
698       value = text;
699       break;
700     }
701     case Toolkit::TextVisual::Property::FONT_FAMILY:
702     {
703       value = mController->GetDefaultFontFamily();
704       break;
705     }
706     case Toolkit::TextVisual::Property::FONT_STYLE:
707     {
708       GetFontStyleProperty( mController, value, Text::FontStyle::DEFAULT );
709       break;
710     }
711     case Toolkit::TextVisual::Property::POINT_SIZE:
712     {
713       value = mController->GetDefaultPointSize();
714       break;
715     }
716     case Toolkit::TextVisual::Property::MULTI_LINE:
717     {
718       value = mController->IsMultiLineEnabled();
719       break;
720     }
721     case Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT:
722     {
723       const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( mController->GetHorizontalAlignment(),
724                                                                                                             HORIZONTAL_ALIGNMENT_STRING_TABLE,
725                                                                                                             HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
726       if( name )
727       {
728         value = std::string( name );
729       }
730       break;
731     }
732     case Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT:
733     {
734       const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( mController->GetVerticalAlignment(),
735                                                                                                           VERTICAL_ALIGNMENT_STRING_TABLE,
736                                                                                                           VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
737       if( name )
738       {
739         value = std::string( name );
740       }
741       break;
742     }
743     case Toolkit::TextVisual::Property::TEXT_COLOR:
744     {
745       value = mController->GetTextColor();
746       break;
747     }
748     case Toolkit::TextVisual::Property::ENABLE_MARKUP:
749     {
750       value = mController->IsMarkupProcessorEnabled();
751       break;
752     }
753     case Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL:
754     {
755       value = mController->IsAutoScrollEnabled();
756       break;
757     }
758     case Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED:
759     {
760       value = mController->GetAutoScrollSpeed();
761       break;
762     }
763     case Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT:
764     {
765       value = mController->GetAutoScrollLoopCount();
766       break;
767     }
768     case Toolkit::TextVisual::Property::AUTO_SCROLL_GAP:
769     {
770       value = mController->GetAutoScrollWrapGap();
771       break;
772     }
773     case Toolkit::TextVisual::Property::LINE_SPACING:
774     {
775       value = mController->GetDefaultLineSpacing();
776       break;
777     }
778     case Toolkit::TextVisual::Property::UNDERLINE:
779     {
780       GetUnderlineProperties( mController, value, Text::EffectStyle::DEFAULT );
781       break;
782     }
783     case Toolkit::TextVisual::Property::SHADOW:
784     {
785       GetShadowProperties( mController, value, Text::EffectStyle::DEFAULT );
786       break;
787     }
788     case Toolkit::TextVisual::Property::EMBOSS:
789     {
790       GetEmbossProperties( mController, value, Text::EffectStyle::DEFAULT );
791       break;
792     }
793     case Toolkit::TextVisual::Property::OUTLINE:
794     {
795       GetOutlineProperties( mController, value, Text::EffectStyle::DEFAULT );
796       break;
797     }
798     case Toolkit::TextVisual::Property::BATCHING_ENABLED:
799     {
800       // TODO
801       break;
802     }
803     default:
804     {
805       // Should not arrive here.
806       DALI_ASSERT_DEBUG( false );
807     }
808   }
809
810   return value;
811 }
812
813 void TextVisual::RenderText()
814 {
815   Actor renderableActor;
816
817   if( mRenderer )
818   {
819     renderableActor = mRenderer->Render( mController->GetView(), Toolkit::DepthIndex::TEXT );
820   }
821
822   if( renderableActor != mRenderableActor )
823   {
824     UnparentAndReset( mRenderableActor );
825
826     if( renderableActor )
827     {
828       const Vector2& scrollOffset = mController->GetScrollPosition();
829       renderableActor.SetPosition( scrollOffset.x, scrollOffset.y );
830
831       mSelf.Add( renderableActor );
832     }
833     mRenderableActor = renderableActor;
834
835     if( mController->IsAutoScrollEnabled() )
836     {
837       SetUpAutoScrolling();
838     }
839   }
840 }
841
842 void TextVisual::StopTextAutoScrolling()
843 {
844   if( mTextScroller )
845   {
846     mTextScroller->StopScrolling();
847   }
848 }
849
850 void TextVisual::SetUpAutoScrolling()
851 {
852   const Text::ScrollerData* const data = mController->GetAutoScrollData();
853
854   if( NULL != data )
855   {
856     if( !mTextScroller )
857     {
858       // If speed, loopCount or gap not set via property system then will need to create a TextScroller with defaults
859       mTextScroller = Text::TextScroller::New( *mController );
860     }
861
862     mTextScroller->StartScrolling( mRenderableActor,
863                                    *data );
864
865     mSelf.Add( mTextScroller->GetScrollingText() );
866     mSelf.Add( mTextScroller->GetSourceCamera() );
867   }
868 }
869
870 } // namespace Internal
871
872 } // namespace Toolkit
873
874 } // namespace Dali