Pre-multiplied Alpha support for ImageView
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / image-view / image-view-impl.cpp
1 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
2
3 // CLASS HEADER
4 #include "image-view-impl.h"
5
6 // EXTERNAL INCLUDES
7 #include <dali/public-api/images/resource-image.h>
8 #include <dali/public-api/object/type-registry.h>
9 #include <dali/devel-api/object/type-registry-helper.h>
10 #include <dali/devel-api/scripting/scripting.h>
11
12 // INTERNAL INCLUDES
13 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
14 #include <dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h>
15 #include <dali-toolkit/internal/controls/renderers/image/image-renderer.h>
16
17 namespace Dali
18 {
19
20 namespace Toolkit
21 {
22
23 namespace Internal
24 {
25
26 namespace
27 {
28
29 BaseHandle Create()
30 {
31   return Toolkit::ImageView::New();
32 }
33
34 // Setup properties, signals and actions using the type-registry.
35 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::ImageView, Toolkit::Control, Create );
36 DALI_PROPERTY_REGISTRATION( Toolkit, ImageView, "resourceUrl", STRING, RESOURCE_URL )
37 DALI_PROPERTY_REGISTRATION( Toolkit, ImageView, "image", MAP, IMAGE )
38 DALI_PROPERTY_REGISTRATION( Toolkit, ImageView, "preMultipliedAlpha", BOOLEAN, PRE_MULTIPLIED_ALPHA )
39
40 DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT( Toolkit, ImageView, "pixelArea", Vector4(0.f, 0.f, 1.f, 1.f), PIXEL_AREA )
41 DALI_TYPE_REGISTRATION_END()
42
43 } // anonymous namespace
44
45 using namespace Dali;
46
47 ImageView::ImageView()
48 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
49   mPremultipledAlphaEnabled( false )
50 {
51 }
52
53 ImageView::~ImageView()
54 {
55 }
56
57 Toolkit::ImageView ImageView::New()
58 {
59   ImageView* impl = new ImageView();
60
61   Toolkit::ImageView handle = Toolkit::ImageView( *impl );
62
63   // Second-phase init of the implementation
64   // This can only be done after the CustomActor connection has been made...
65   impl->Initialize();
66
67   return handle;
68 }
69
70 /////////////////////////////////////////////////////////////
71
72 void ImageView::SetImage( Image image )
73 {
74   if( ( mImage != image ) ||
75       ! mUrl.empty()      ||   // If we're changing from a URL type to an Image type
76       ! mPropertyMap.Empty() ) // If we're changing from a property map type to an Image type
77   {
78     mUrl.clear();
79     mPropertyMap.Clear();
80
81     mImage = image;
82
83     Actor self = Self();
84     Toolkit::RendererFactory::Get().ResetRenderer( mRenderer, self, image );
85     mImageSize = image ? ImageDimensions( image.GetWidth(), image.GetHeight() ) : ImageDimensions( 0, 0 );
86
87     RelayoutRequest();
88   }
89 }
90
91 void ImageView::SetImage( Property::Map map )
92 {
93   mUrl.clear();
94   mImage.Reset();
95   mPropertyMap = map;
96
97   Actor self = Self();
98   Toolkit::RendererFactory::Get().ResetRenderer( mRenderer, self, mPropertyMap );
99
100   Property::Value* widthValue = mPropertyMap.Find( "width" );
101   if( widthValue )
102   {
103     int width;
104     if( widthValue->Get( width ) )
105     {
106       mImageSize = ImageDimensions( width, mImageSize.GetHeight() );
107     }
108   }
109
110   Property::Value* heightValue = mPropertyMap.Find( "height" );
111   if( heightValue )
112   {
113     int height;
114     if( heightValue->Get( height ) )
115     {
116       mImageSize = ImageDimensions( mImageSize.GetWidth(), height );
117     }
118   }
119
120   RelayoutRequest();
121 }
122
123 void ImageView::SetImage( const std::string& url, ImageDimensions size )
124 {
125   if( ( mUrl != url ) ||
126       mImage          ||       // If we're changing from an Image type to a URL type
127       ! mPropertyMap.Empty() ) // If we're changing from a property map type to a URL type
128   {
129     mImage.Reset();
130     mPropertyMap.Clear();
131
132     mUrl = url;
133
134     if( size.GetWidth() == 0u && size.GetHeight() == 0u )
135     {
136       mImageSize = ResourceImage::GetImageSize( mUrl );
137     }
138     else
139     {
140       mImageSize = size;
141     }
142
143     Actor self = Self();
144     Toolkit::RendererFactory::Get().ResetRenderer( mRenderer, self, mUrl, mImageSize );
145
146     RelayoutRequest();
147   }
148 }
149
150 void ImageView::EnablePreMultipliedAlpha( bool preMultipled )
151 {
152   mPremultipledAlphaEnabled = preMultipled;
153
154   if( mRenderer )
155   {
156     ControlRenderer& rendererImpl = GetImplementation( mRenderer );
157     if (&typeid( rendererImpl ) == &typeid(ImageRenderer) )
158     {
159       ImageRenderer* imageRenderer = static_cast<ImageRenderer*>( &rendererImpl );
160       imageRenderer->EnablePreMultipliedAlpha( preMultipled );
161     }
162   }
163 }
164
165 bool ImageView::IsPreMultipliedAlphaEnabled() const
166 {
167   return mPremultipledAlphaEnabled;
168 }
169
170 void ImageView::SetDepthIndex( int depthIndex )
171 {
172   if( mRenderer )
173   {
174     mRenderer.SetDepthIndex( depthIndex );
175   }
176 }
177
178 Vector3 ImageView::GetNaturalSize()
179 {
180   Vector3 size;
181
182   size.x = mImageSize.GetWidth();
183   size.y = mImageSize.GetHeight();
184
185   if( size.x > 0 && size.y > 0 )
186   {
187     size.z = std::min(size.x, size.y);
188     return size;
189   }
190   else
191   {
192     // if no image then use Control's natural size
193     return Control::GetNaturalSize();
194   }
195 }
196
197 float ImageView::GetHeightForWidth( float width )
198 {
199   if( mImageSize.GetWidth() > 0 && mImageSize.GetHeight() > 0 )
200   {
201     return GetHeightForWidthBase( width );
202   }
203   else
204   {
205     return Control::GetHeightForWidth( width );
206   }
207 }
208
209 float ImageView::GetWidthForHeight( float height )
210 {
211   if( mImageSize.GetWidth() > 0 && mImageSize.GetHeight() > 0 )
212   {
213     return GetWidthForHeightBase( height );
214   }
215   else
216   {
217     return Control::GetWidthForHeight( height );
218   }
219 }
220
221
222 ///////////////////////////////////////////////////////////
223 //
224 // Private methods
225 //
226
227 void ImageView::OnStageConnection( int depth )
228 {
229   Control::OnStageConnection( depth );
230
231   if( mRenderer )
232   {
233     CustomActor self = Self();
234     mRenderer.SetOnStage( self );
235   }
236 }
237
238 void ImageView::OnStageDisconnection()
239 {
240   if( mRenderer )
241   {
242     CustomActor self = Self();
243     mRenderer.SetOffStage( self );
244   }
245
246   Control::OnStageDisconnection();
247 }
248
249 ///////////////////////////////////////////////////////////
250 //
251 // Properties
252 //
253
254 void ImageView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
255 {
256   Toolkit::ImageView imageView = Toolkit::ImageView::DownCast( Dali::BaseHandle( object ) );
257
258   if ( imageView )
259   {
260     switch ( index )
261     {
262       case Toolkit::ImageView::Property::RESOURCE_URL:
263       {
264         std::string imageUrl;
265         if( value.Get( imageUrl ) )
266         {
267           GetImpl( imageView ).SetImage( imageUrl, ImageDimensions() );
268         }
269         break;
270       }
271
272       case Toolkit::ImageView::Property::IMAGE:
273       {
274         std::string imageUrl;
275         if( value.Get( imageUrl ) )
276         {
277           ImageView& impl = GetImpl( imageView );
278           impl.SetImage( imageUrl, ImageDimensions() );
279         }
280
281         // if its not a string then get a Property::Map from the property if possible.
282         Property::Map map;
283         if( value.Get( map ) )
284         {
285           ImageView& impl = GetImpl( imageView );
286           impl.SetImage( map );
287         }
288
289         break;
290       }
291
292       case Toolkit::ImageView::Property::PRE_MULTIPLIED_ALPHA:
293       {
294         bool IsPre;
295         if( value.Get( IsPre ) )
296         {
297           GetImpl(imageView).EnablePreMultipliedAlpha( IsPre );
298         }
299         break;
300       }
301     }
302   }
303 }
304
305 Property::Value ImageView::GetProperty( BaseObject* object, Property::Index propertyIndex )
306 {
307   Property::Value value;
308
309   Toolkit::ImageView imageview = Toolkit::ImageView::DownCast( Dali::BaseHandle( object ) );
310
311   if ( imageview )
312   {
313     ImageView& impl = GetImpl( imageview );
314     switch ( propertyIndex )
315     {
316       case Toolkit::ImageView::Property::RESOURCE_URL:
317       {
318         if ( !impl.mUrl.empty() )
319         {
320           value = impl.mUrl;
321         }
322         break;
323       }
324
325       case Toolkit::ImageView::Property::IMAGE:
326       {
327         if ( !impl.mUrl.empty() )
328         {
329           value = impl.mUrl;
330         }
331         else if( impl.mImage )
332         {
333           Property::Map map;
334           Scripting::CreatePropertyMap( impl.mImage, map );
335           value = map;
336         }
337         else if( !impl.mPropertyMap.Empty() )
338         {
339           value = impl.mPropertyMap;
340         }
341         break;
342       }
343
344       case Toolkit::ImageView::Property::PRE_MULTIPLIED_ALPHA:
345       {
346         value = impl.IsPreMultipliedAlphaEnabled();
347         break;
348       }
349     }
350   }
351
352   return value;
353 }
354
355 } // namespace Internal
356 } // namespace Toolkit
357 } // namespace Dali