e70f1820c9ebb48aee2508ad7162e7b01d4163b4
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / image-actor-impl.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/internal/event/actors/image-actor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/animation/constraints.h> // for EqualToConstraint
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/public-api/rendering/renderer.h>
28 #include <dali/devel-api/scripting/scripting.h>
29 #include <dali/internal/event/animation/constraint-impl.h>
30 #include <dali/internal/event/common/property-helper.h>
31 #include <dali/internal/event/effects/shader-effect-impl.h>
32 #include <dali/internal/event/images/image-connector.h>
33 #include <dali/internal/event/images/nine-patch-image-impl.h>
34
35 namespace Dali
36 {
37
38 namespace Internal
39 {
40
41 namespace
42 {
43
44 // Properties
45
46 //              Name           Type   writable animatable constraint-input  enum for index-checking
47 DALI_PROPERTY_TABLE_BEGIN
48 DALI_PROPERTY( "pixelArea",    RECTANGLE, true,    false,   true,    Dali::ImageActor::Property::PIXEL_AREA )
49 DALI_PROPERTY( "style",        STRING,    true,    false,   true,    Dali::ImageActor::Property::STYLE      )
50 DALI_PROPERTY( "border",       VECTOR4,   true,    false,   true,    Dali::ImageActor::Property::BORDER     )
51 DALI_PROPERTY( "image",        MAP,       true,    false,   false,   Dali::ImageActor::Property::IMAGE      )
52 DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX )
53
54 BaseHandle Create()
55 {
56   return Dali::ImageActor::New();
57 }
58
59 TypeRegistration mType( typeid( Dali::ImageActor ), typeid( Dali::Actor ), Create );
60
61 struct GridVertex
62 {
63   GridVertex( float positionX, float positionY, const Vector2& size )
64   : mPosition( positionX*size.x, positionY*size.y, 0.f ),
65     mTextureCoord( positionX+0.5f, positionY+0.5f )
66   {
67   }
68
69   Vector3 mPosition;
70   Vector2 mTextureCoord;
71 };
72
73 GeometryPtr CreateGeometry( unsigned int gridWidth, unsigned int gridHeight, const Vector2& size )
74 {
75   // Create vertices
76   std::vector< GridVertex > vertices;
77   vertices.reserve( ( gridWidth + 1 ) * ( gridHeight + 1 ) );
78
79   for( unsigned int y = 0u; y < gridHeight + 1; ++y )
80   {
81     float yPos = (float)y / gridHeight;
82     for( unsigned int x = 0u; x < gridWidth + 1; ++x )
83     {
84       float xPos = (float)x / gridWidth;
85       vertices.push_back( GridVertex( xPos - 0.5f, yPos - 0.5f, size ) );
86     }
87   }
88
89   // Create indices
90   Vector< unsigned short > indices;
91   indices.Reserve( ( gridWidth + 2 ) * gridHeight * 2 - 2);
92
93   for( unsigned int row = 0u; row < gridHeight; ++row )
94   {
95     unsigned int rowStartIndex = row*(gridWidth+1u);
96     unsigned int nextRowStartIndex = rowStartIndex + gridWidth +1u;
97
98     if( row != 0u ) // degenerate index on non-first row
99     {
100       indices.PushBack( rowStartIndex );
101     }
102
103     for( unsigned int column = 0u; column < gridWidth+1u; column++) // main strip
104     {
105       indices.PushBack( rowStartIndex + column);
106       indices.PushBack( nextRowStartIndex + column);
107     }
108
109     if( row != gridHeight-1u ) // degenerate index on non-last row
110     {
111       indices.PushBack( nextRowStartIndex + gridWidth );
112     }
113   }
114
115   Property::Map vertexFormat;
116   vertexFormat[ "aPosition" ] = Property::VECTOR3;
117   vertexFormat[ "aTexCoord" ] = Property::VECTOR2;
118   PropertyBufferPtr vertexPropertyBuffer = PropertyBuffer::New( vertexFormat );
119   if( vertices.size() > 0 )
120   {
121     vertexPropertyBuffer->SetData( &vertices[ 0 ], vertices.size() );
122   }
123
124   // Create the geometry object
125   GeometryPtr geometry = Geometry::New();
126   geometry->AddVertexBuffer( *vertexPropertyBuffer );
127   if( indices.Size() > 0 )
128   {
129     geometry->SetIndexBuffer( &indices[0], indices.Size() );
130   }
131   geometry->SetGeometryType( Dali::Geometry::TRIANGLE_STRIP );
132
133   return geometry;
134 }
135
136 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
137   attribute mediump vec3 aPosition;\n
138   attribute mediump vec2 aTexCoord;\n
139   varying mediump vec2 vTexCoord;\n
140   uniform mediump mat4 uMvpMatrix;\n
141   uniform mediump vec3 uSize;\n
142   uniform mediump vec4 sTextureRect;\n
143   \n
144   void main()\n
145   {\n
146     gl_Position = uMvpMatrix * vec4(aPosition, 1.0);\n
147     vTexCoord = aTexCoord;\n
148   }\n
149 );
150
151 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
152   varying mediump vec2 vTexCoord;\n
153   uniform sampler2D sTexture;\n
154   uniform lowp vec4 uColor;\n
155   \n
156   void main()\n
157   {\n
158     gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
159   }\n
160 );
161
162 const char * const TEXTURE_RECT_UNIFORM_NAME( "sTextureRect" );
163
164 const int INVALID_RENDERER_ID = -1;
165 const uint16_t MAXIMUM_GRID_SIZE = 2048;
166 }
167
168 ImageActorPtr ImageActor::New()
169 {
170   ImageActorPtr actor( new ImageActor );
171
172   // Second-phase construction of base class
173   actor->Initialize();
174
175   //Create the renderer
176   actor->mRenderer = Renderer::New();
177
178   GeometryPtr quad  = CreateGeometry( 1u, 1u, Vector2::ONE );
179   actor->mRenderer->SetGeometry( *quad );
180
181   ShaderPtr shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER, Dali::Shader::HINT_NONE );
182   actor->mRenderer->SetShader( *shader );
183   TextureSetPtr textureSet = TextureSet::New();
184   actor->mRenderer->SetTextures( *textureSet );
185
186   return actor;
187 }
188
189 void ImageActor::OnInitialize()
190 {
191   // TODO: Remove this, at the moment its needed for size negotiation to work
192   SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
193 }
194
195 void ImageActor::SetImage( ImagePtr& image )
196 {
197   if( !image )
198   {
199     if( mRendererIndex != INVALID_RENDERER_ID )
200     {
201       RemoveRenderer( mRendererIndex );
202       mRendererIndex = INVALID_RENDERER_ID;
203     }
204   }
205   else
206   {
207     SamplerPtr sampler = Sampler::New();
208     sampler->SetFilterMode( mMinFilter, mMagFilter );
209
210     TextureSet* textureSet( mRenderer->GetTextures() );
211     textureSet->SetImage( 0u, image.Get() );
212     textureSet->SetSampler( 0u, sampler );
213
214     if( mRendererIndex == INVALID_RENDERER_ID )
215     {
216       mRendererIndex = AddRenderer( *mRenderer );
217     }
218
219     if( !mIsPixelAreaSet )
220     {
221       mPixelArea = PixelArea( 0, 0, image->GetWidth(), image->GetHeight() );
222     }
223
224     RelayoutRequest();
225     UpdateTexureRect();
226   }
227 }
228
229 ImagePtr ImageActor::GetImage() const
230 {
231   return mRenderer->GetTextures()->GetImage( 0u );
232 }
233
234 void ImageActor::SetPixelArea( const PixelArea& pixelArea )
235 {
236   mPixelArea = pixelArea;
237   mIsPixelAreaSet = true;
238
239   RelayoutRequest();
240   UpdateTexureRect();
241 }
242
243 const ImageActor::PixelArea& ImageActor::GetPixelArea() const
244 {
245   return mPixelArea;
246 }
247
248 bool ImageActor::IsPixelAreaSet() const
249 {
250   return mIsPixelAreaSet;
251 }
252
253 void ImageActor::ClearPixelArea()
254 {
255   mIsPixelAreaSet = false;
256
257   int imageWidth = 0;
258   int imageHeight = 0;
259   ImagePtr image = GetImage();
260   if( image )
261   {
262     imageWidth = image->GetWidth();
263     imageHeight = image->GetHeight();
264   }
265
266   mPixelArea = PixelArea( 0, 0, imageWidth, imageHeight );
267
268   RelayoutRequest();
269   UpdateTexureRect();
270 }
271
272 void ImageActor::SetStyle( Dali::ImageActor::Style style )
273 {
274   DALI_LOG_WARNING( "SetStyle Deprecated. Only STYLE_QUAD supported." );
275   mStyle = style;
276 }
277
278 Dali::ImageActor::Style ImageActor::GetStyle() const
279 {
280   DALI_LOG_WARNING( "GetStyle Deprecated. Only STYLE_QUAD supported." );
281   return mStyle;
282 }
283
284 void ImageActor::SetNinePatchBorder( const Vector4& border )
285 {
286   DALI_LOG_WARNING( "SetNinePatchBorder Deprecated. Only STYLE_QUAD supported." );
287   mNinePatchBorder = border;
288 }
289
290 Vector4 ImageActor::GetNinePatchBorder() const
291 {
292   DALI_LOG_WARNING( "GetNinePatchBorder Deprecated. Only STYLE_QUAD supported." );
293   return mNinePatchBorder;
294 }
295
296 ImageActor::ImageActor()
297 : Actor( Actor::BASIC ),
298   mActorSize( Vector2::ZERO ),
299   mGridSize( 1u, 1u ),
300   mRendererIndex( INVALID_RENDERER_ID ),
301   mMinFilter( FilterMode::DEFAULT ),
302   mMagFilter( FilterMode::DEFAULT ),
303   mStyle( Dali::ImageActor::STYLE_QUAD ),
304   mIsPixelAreaSet( false )
305 {
306 }
307
308 ImageActor::~ImageActor()
309 {
310 }
311
312 Vector3 ImageActor::GetNaturalSize() const
313 {
314   Vector2 naturalSize( CalculateNaturalSize() );
315   return Vector3( naturalSize.width, naturalSize.height, 0.f );
316 }
317
318 Vector2 ImageActor::CalculateNaturalSize() const
319 {
320   // if no image then natural size is 0
321   Vector2 size( 0.0f, 0.0f );
322
323   ImagePtr image = GetImage();
324   if( image )
325   {
326     if( IsPixelAreaSet() )
327     {
328       PixelArea area(GetPixelArea());
329       size.width = area.width;
330       size.height = area.height;
331     }
332     else
333     {
334       size = image->GetNaturalSize();
335     }
336   }
337
338   return size;
339 }
340
341 void ImageActor::UpdateGeometry()
342 {
343   uint16_t gridWidth = 1u;
344   uint16_t gridHeight = 1u;
345
346   if( mShaderEffect )
347   {
348     Vector2 gridSize = mShaderEffect->GetGridSize( Vector2(mPixelArea.width, mPixelArea.height) );
349
350     //limit the grid size
351     gridWidth = std::min( MAXIMUM_GRID_SIZE, static_cast<uint16_t>(gridSize.width) );
352     gridHeight = std::min( MAXIMUM_GRID_SIZE, static_cast<uint16_t>(gridSize.height) );
353   }
354
355   mGridSize.SetWidth( gridWidth );
356   mGridSize.SetHeight( gridHeight );
357
358   GeometryPtr geometry = CreateGeometry( gridWidth, gridHeight, mActorSize );
359   mRenderer->SetGeometry( *geometry );
360 }
361 void ImageActor::UpdateTexureRect()
362 {
363   Vector4 textureRect( 0.f, 0.f, 1.f, 1.f );
364
365   ImagePtr image = GetImage();
366   if( mIsPixelAreaSet && image )
367   {
368     const float uScale = 1.0f / float(image->GetWidth());
369     const float vScale = 1.0f / float(image->GetHeight());
370     // bottom left
371     textureRect.x = uScale * float(mPixelArea.x);
372     textureRect.y = vScale * float(mPixelArea.y);
373     // top right
374     textureRect.z  = uScale * float(mPixelArea.x + mPixelArea.width);
375     textureRect.w = vScale * float(mPixelArea.y + mPixelArea.height);
376   }
377
378   mRenderer->RegisterProperty( TEXTURE_RECT_UNIFORM_NAME, textureRect );
379 }
380
381 unsigned int ImageActor::GetDefaultPropertyCount() const
382 {
383   return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
384 }
385
386 void ImageActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
387 {
388   Actor::GetDefaultPropertyIndices( indices ); // Actor class properties
389
390   indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
391
392   int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
393   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
394   {
395     indices.PushBack( index );
396   }
397 }
398
399 bool ImageActor::IsDefaultPropertyWritable( Property::Index index ) const
400 {
401   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
402   {
403     return Actor::IsDefaultPropertyWritable(index);
404   }
405
406   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
407   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
408   {
409     return DEFAULT_PROPERTY_DETAILS[ index ].writable;
410   }
411
412   return false;
413 }
414
415 bool ImageActor::IsDefaultPropertyAnimatable( Property::Index index ) const
416 {
417   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
418   {
419     return Actor::IsDefaultPropertyAnimatable( index );
420   }
421
422   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
423   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
424   {
425     return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
426   }
427
428   return false;
429 }
430
431 bool ImageActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
432 {
433   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
434   {
435     return Actor::IsDefaultPropertyAConstraintInput( index );
436   }
437
438   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
439   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
440   {
441     return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
442   }
443
444   return false;
445 }
446
447 Property::Type ImageActor::GetDefaultPropertyType( Property::Index index ) const
448 {
449   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
450   {
451     return Actor::GetDefaultPropertyType( index );
452   }
453
454   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
455   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
456   {
457     return DEFAULT_PROPERTY_DETAILS[index].type;
458   }
459
460   // index out-of-bounds
461   return Property::NONE;
462 }
463
464 const char* ImageActor::GetDefaultPropertyName( Property::Index index ) const
465 {
466   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
467   {
468     return Actor::GetDefaultPropertyName(index);
469   }
470
471   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
472   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
473   {
474     return DEFAULT_PROPERTY_DETAILS[index].name;
475   }
476
477   // index out-of-bounds
478   return NULL;
479 }
480
481 Property::Index ImageActor::GetDefaultPropertyIndex(const std::string& name) const
482 {
483   Property::Index index = Property::INVALID_INDEX;
484
485   // Look for name in default properties
486   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
487   {
488     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
489     if( 0 == strcmp( name.c_str(), property->name ) ) // Don't want to convert rhs to string
490     {
491       index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
492       break;
493     }
494   }
495
496   // If not found, check in base class
497   if( Property::INVALID_INDEX == index )
498   {
499     index = Actor::GetDefaultPropertyIndex( name );
500   }
501   return index;
502 }
503
504 void ImageActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
505 {
506   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
507   {
508     Actor::SetDefaultProperty( index, propertyValue );
509   }
510   else
511   {
512     switch(index)
513     {
514       case Dali::ImageActor::Property::PIXEL_AREA:
515       {
516         SetPixelArea(propertyValue.Get<Rect<int> >());
517         break;
518       }
519       case Dali::ImageActor::Property::STYLE:
520       {
521         //not supported
522         break;
523       }
524       case Dali::ImageActor::Property::BORDER:
525       {
526         //not supported
527         break;
528       }
529       case Dali::ImageActor::Property::IMAGE:
530       {
531         Dali::Image img = Scripting::NewImage( propertyValue );
532         if(img)
533         {
534           ImagePtr image( &GetImplementation(img) );
535           SetImage( image );
536         }
537         else
538         {
539           DALI_LOG_WARNING("Cannot create image from property value\n");
540         }
541         break;
542       }
543       default:
544       {
545         DALI_LOG_WARNING("Unknown property (%d)\n", index);
546         break;
547       }
548     } // switch(index)
549
550   } // else
551 }
552
553 Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const
554 {
555   Property::Value ret;
556   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
557   {
558     ret = Actor::GetDefaultProperty( index );
559   }
560   else
561   {
562     switch( index )
563     {
564       case Dali::ImageActor::Property::PIXEL_AREA:
565       {
566         Rect<int> r = GetPixelArea();
567         ret = r;
568         break;
569       }
570       case Dali::ImageActor::Property::STYLE:
571       {
572         //not supported
573         break;
574       }
575       case Dali::ImageActor::Property::BORDER:
576       {
577         //not supported
578         break;
579       }
580       case Dali::ImageActor::Property::IMAGE:
581       {
582         Property::Map map;
583         Scripting::CreatePropertyMap( Dali::Image( GetImage().Get() ), map );
584         ret = Property::Value( map );
585         break;
586       }
587       default:
588       {
589         DALI_LOG_WARNING( "Unknown property (%d)\n", index );
590         break;
591       }
592     } // switch(index)
593   }
594
595   return ret;
596 }
597
598 void ImageActor::SetSortModifier(float modifier)
599 {
600   mRenderer->SetDepthIndex( modifier );
601 }
602
603 float ImageActor::GetSortModifier() const
604 {
605   return mRenderer->GetDepthIndex();
606 }
607
608 void ImageActor::SetBlendMode( BlendingMode::Type mode )
609 {
610   mRenderer->SetBlendMode( static_cast<BlendMode::Type>( mode ) );
611 }
612
613 BlendingMode::Type ImageActor::GetBlendMode() const
614 {
615   return static_cast<BlendingMode::Type>( mRenderer->GetBlendMode() );
616 }
617
618 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgba,   BlendingFactor::Type destFactorRgba )
619 {
620   mRenderer->SetBlendFunc( static_cast<BlendFactor::Type>(srcFactorRgba), static_cast<BlendFactor::Type>(destFactorRgba), static_cast<BlendFactor::Type>(srcFactorRgba), static_cast<BlendFactor::Type>(destFactorRgba) );
621 }
622
623 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
624                                BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha )
625 {
626   mRenderer->SetBlendFunc( static_cast<BlendFactor::Type>(srcFactorRgb), static_cast<BlendFactor::Type>(destFactorRgb), static_cast<BlendFactor::Type>(srcFactorAlpha), static_cast<BlendFactor::Type>(destFactorAlpha) );
627 }
628
629 void ImageActor::GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
630                                BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const
631 {
632   mRenderer->GetBlendFunc( reinterpret_cast<BlendFactor::Type&>(srcFactorRgb), reinterpret_cast<BlendFactor::Type&>(destFactorRgb), reinterpret_cast<BlendFactor::Type&>(srcFactorAlpha), reinterpret_cast<BlendFactor::Type&>(destFactorAlpha) );
633 }
634
635 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgba )
636 {
637   mRenderer->SetBlendEquation( static_cast<BlendEquation::Type>(equationRgba), static_cast<BlendEquation::Type>(equationRgba) );
638 }
639
640 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha )
641 {
642   mRenderer->SetBlendEquation( static_cast<BlendEquation::Type>(equationRgb), static_cast<BlendEquation::Type>(equationAlpha) );
643 }
644
645 void ImageActor::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const
646 {
647   mRenderer->GetBlendEquation( reinterpret_cast<BlendEquation::Type&>(equationRgb), reinterpret_cast<BlendEquation::Type&>(equationAlpha) );
648 }
649
650 void ImageActor::SetBlendColor( const Vector4& color )
651 {
652   mBlendColor = color;
653   mRenderer->SetBlendColor( mBlendColor );
654 }
655
656 const Vector4& ImageActor::GetBlendColor() const
657 {
658   return mBlendColor;
659 }
660
661 void ImageActor::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter )
662 {
663   mMinFilter = minFilter;
664   mMagFilter = magFilter;
665
666   SamplerPtr sampler = Sampler::New();
667   sampler->SetFilterMode( minFilter, magFilter );
668   mRenderer->GetTextures()->SetSampler( 0u, sampler.Get() );
669 }
670
671 void ImageActor::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const
672 {
673   minFilter = mMinFilter;
674   magFilter = mMagFilter;
675 }
676
677 void ImageActor::SetShaderEffect( ShaderEffect& effect )
678 {
679   if( mShaderEffect )
680   {
681     mShaderEffect->Disconnect( this );
682   }
683
684   mShaderEffect = ShaderEffectPtr( &effect );
685   effect.Connect( this );
686
687   ShaderPtr shader = mShaderEffect->GetShader();
688   mRenderer->SetShader( *shader );
689
690   EffectImageUpdated();
691
692   UpdateGeometry();
693 }
694
695 ShaderEffectPtr ImageActor::GetShaderEffect() const
696 {
697   return mShaderEffect;
698 }
699
700 void ImageActor::RemoveShaderEffect()
701 {
702   if( mShaderEffect )
703   {
704     mShaderEffect->Disconnect( this );
705     // change to the standard shader and quad geometry
706     ShaderPtr shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER, Dali::Shader::HINT_NONE );
707     mRenderer->SetShader( *shader );
708     mShaderEffect.Reset();
709
710     UpdateGeometry();
711   }
712 }
713
714 void ImageActor::EffectImageUpdated()
715 {
716   if( mShaderEffect )
717   {
718     Dali::Image effectImage = mShaderEffect->GetEffectImage();
719     if( effectImage )
720     {
721       Image& effectImageImpl = GetImplementation( effectImage );
722       mRenderer->GetTextures()->SetImage( 1u, &effectImageImpl );
723     }
724     else
725     {
726        mRenderer->GetTextures()->SetImage( 1u, 0 );
727     }
728   }
729 }
730
731 void ImageActor::OnRelayout( const Vector2& size, RelayoutContainer& container )
732 {
733   if( mActorSize != size )
734   {
735     mActorSize = size;
736     UpdateGeometry();
737   }
738 }
739
740 void ImageActor::OnSizeSet( const Vector3& targetSize )
741 {
742   Vector2 size( targetSize.x, targetSize.y );
743   if( mActorSize != size )
744   {
745     mActorSize = size;
746     UpdateGeometry();
747   }
748 }
749
750 } // namespace Internal
751
752 } // namespace Dali