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