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