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