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