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