Merge remote-tracking branch 'origin/tizen' into devel/new_mesh
[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/object/type-registry.h>
26 #include <dali/devel-api/scripting/scripting.h>
27 #include <dali/internal/event/common/property-helper.h>
28 #include <dali/internal/event/effects/shader-effect-impl.h>
29 #include <dali/internal/event/images/image-connector.h>
30 #include <dali/internal/event/images/nine-patch-image-impl.h>
31
32 namespace Dali
33 {
34
35 namespace Internal
36 {
37
38 namespace
39 {
40
41 // Properties
42
43 //              Name           Type   writable animatable constraint-input  enum for index-checking
44 DALI_PROPERTY_TABLE_BEGIN
45 DALI_PROPERTY( "pixel-area",   RECTANGLE, true,    false,   true,    Dali::ImageActor::Property::PIXEL_AREA )
46 DALI_PROPERTY( "style",        STRING,    true,    false,   true,    Dali::ImageActor::Property::STYLE      )
47 DALI_PROPERTY( "border",       VECTOR4,   true,    false,   true,    Dali::ImageActor::Property::BORDER     )
48 DALI_PROPERTY( "image",        MAP,       true,    false,   false,   Dali::ImageActor::Property::IMAGE      )
49 DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX )
50
51 BaseHandle Create()
52 {
53   return Dali::ImageActor::New();
54 }
55
56 TypeRegistration mType( typeid( Dali::ImageActor ), typeid( Dali::RenderableActor ), Create );
57
58 ImageActor::Style StyleEnum(const std::string &s)
59 {
60   if(s == "STYLE_NINE_PATCH")
61   {
62     return Dali::ImageActor::STYLE_NINE_PATCH;
63   }
64   else if(s == "STYLE_NINE_PATCH_NO_CENTER")
65   {
66     return Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER;
67   }
68   else // if(s == "QUAD")
69   {
70     return Dali::ImageActor::STYLE_QUAD;
71   }
72 }
73
74 std::string StyleString(const ImageActor::Style style)
75 {
76   if(style == Dali::ImageActor::STYLE_NINE_PATCH)
77   {
78     return "STYLE_NINE_PATCH";
79   }
80   else if(style == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER)
81   {
82     return "STYLE_NINE_PATCH_NO_CENTER";
83   }
84   else // if(s == "QUAD")
85   {
86     return "STYLE_QUAD";
87   }
88 }
89 }
90
91 ImageActorPtr ImageActor::New()
92 {
93   ImageActorPtr actor( new ImageActor );
94
95   // Second-phase construction of base class
96   actor->Initialize();
97
98   // Create the attachment
99   actor->mImageAttachment = ImageAttachment::New( actor->GetEventThreadServices(), *actor->mNode );
100   actor->Attach( *actor->mImageAttachment );
101
102   return actor;
103 }
104
105 void ImageActor::OnInitialize()
106 {
107   SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
108 }
109
110 void ImageActor::SetImage( ImagePtr& image )
111 {
112   ImagePtr currentImage = mImageAttachment->GetImage();
113   // early exit if it's the same image as we already have
114   if ( currentImage == image )
115   {
116     return;
117   }
118
119   // NOTE! image might be pointing to NULL, which is fine as in that case app wants to just remove the image
120   ImagePtr newImage( image );
121   // if image is not NULL, check for 9 patch
122   if( newImage )
123   {
124     // Automatically convert nine-patch images to cropped bitmap
125     NinePatchImage* ninePatchImage = NinePatchImage::DownCast( image.Get() );
126     if( ninePatchImage )
127     {
128       newImage = ninePatchImage->CreateCroppedBufferImage();
129       SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
130       SetNinePatchBorder( ninePatchImage->GetStretchBorders(), true );
131     }
132   }
133   // set the actual image (normal or 9 patch) and natural size based on that
134   mImageAttachment->SetImage( newImage );
135
136   RelayoutRequest();
137 }
138
139 ImagePtr ImageActor::GetImage()
140 {
141   return mImageAttachment->GetImage();
142 }
143
144 void ImageActor::SetPixelArea( const PixelArea& pixelArea )
145 {
146   mImageAttachment->SetPixelArea( pixelArea );
147
148   RelayoutRequest();
149 }
150
151 const ImageActor::PixelArea& ImageActor::GetPixelArea() const
152 {
153   return mImageAttachment->GetPixelArea();
154 }
155
156 bool ImageActor::IsPixelAreaSet() const
157 {
158   return mImageAttachment->IsPixelAreaSet();
159 }
160
161 void ImageActor::ClearPixelArea()
162 {
163   mImageAttachment->ClearPixelArea();
164
165   RelayoutRequest();
166 }
167
168 void ImageActor::SetStyle( Style style )
169 {
170   mImageAttachment->SetStyle( style );
171 }
172
173 ImageActor::Style ImageActor::GetStyle() const
174 {
175   return mImageAttachment->GetStyle();
176 }
177
178 void ImageActor::SetNinePatchBorder( const Vector4& border, bool inPixels )
179 {
180   mImageAttachment->SetNinePatchBorder( border, inPixels );
181 }
182
183 Vector4 ImageActor::GetNinePatchBorder() const
184 {
185   return mImageAttachment->GetNinePatchBorder();
186 }
187
188 ImageAttachment& ImageActor::GetImageAttachment()
189 {
190   return *mImageAttachment;
191 }
192
193 RenderableAttachment& ImageActor::GetRenderableAttachment() const
194 {
195   DALI_ASSERT_DEBUG( mImageAttachment && "ImageAttachment missing from ImageActor" );
196   return *mImageAttachment;
197 }
198
199 ImageActor::ImageActor()
200 : RenderableActor()
201 {
202 }
203
204 ImageActor::~ImageActor()
205 {
206 }
207
208 Vector3 ImageActor::GetNaturalSize() const
209 {
210   Vector2 naturalSize( CalculateNaturalSize() );
211   return Vector3( naturalSize.width, naturalSize.height, CalculateSizeZ( naturalSize ) );
212 }
213
214 Vector2 ImageActor::CalculateNaturalSize() const
215 {
216   // if no image then natural size is 0
217   Vector2 size( 0.0f, 0.0f );
218
219   ImagePtr image = mImageAttachment->GetImage();
220   if( image )
221   {
222     if( IsPixelAreaSet() )
223     {
224       PixelArea area(GetPixelArea());
225       size.width = area.width;
226       size.height = area.height;
227     }
228     else
229     {
230       size = image->GetNaturalSize();
231     }
232   }
233
234   return size;
235 }
236
237 void ImageActor::OnStageConnectionInternal()
238 {
239 }
240
241 void ImageActor::OnStageDisconnectionInternal()
242 {
243 }
244
245 unsigned int ImageActor::GetDefaultPropertyCount() const
246 {
247   return RenderableActor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
248 }
249
250 void ImageActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
251 {
252   RenderableActor::GetDefaultPropertyIndices( indices ); // RenderableActor class properties
253
254   indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
255
256   int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
257   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
258   {
259     indices.PushBack( index );
260   }
261 }
262
263 bool ImageActor::IsDefaultPropertyWritable( Property::Index index ) const
264 {
265   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
266   {
267     return RenderableActor::IsDefaultPropertyWritable(index);
268   }
269
270   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
271   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
272   {
273     return DEFAULT_PROPERTY_DETAILS[ index ].writable;
274   }
275
276   return false;
277 }
278
279 bool ImageActor::IsDefaultPropertyAnimatable( Property::Index index ) const
280 {
281   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
282   {
283     return RenderableActor::IsDefaultPropertyAnimatable( index );
284   }
285
286   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
287   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
288   {
289     return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
290   }
291
292   return false;
293 }
294
295 bool ImageActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
296 {
297   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
298   {
299     return RenderableActor::IsDefaultPropertyAConstraintInput( index );
300   }
301
302   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
303   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
304   {
305     return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
306   }
307
308   return false;
309 }
310
311 Property::Type ImageActor::GetDefaultPropertyType( Property::Index index ) const
312 {
313   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
314   {
315     return RenderableActor::GetDefaultPropertyType( index );
316   }
317
318   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
319   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
320   {
321     return DEFAULT_PROPERTY_DETAILS[index].type;
322   }
323
324   // index out-of-bounds
325   return Property::NONE;
326 }
327
328 const char* ImageActor::GetDefaultPropertyName( Property::Index index ) const
329 {
330   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
331   {
332     return RenderableActor::GetDefaultPropertyName(index);
333   }
334
335   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
336   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
337   {
338     return DEFAULT_PROPERTY_DETAILS[index].name;
339   }
340
341   // index out-of-bounds
342   return NULL;
343 }
344
345 Property::Index ImageActor::GetDefaultPropertyIndex(const std::string& name) const
346 {
347   Property::Index index = Property::INVALID_INDEX;
348
349   // Look for name in default properties
350   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
351   {
352     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
353     if( 0 == strcmp( name.c_str(), property->name ) ) // Don't want to convert rhs to string
354     {
355       index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
356       break;
357     }
358   }
359
360   // If not found, check in base class
361   if( Property::INVALID_INDEX == index )
362   {
363     index = RenderableActor::GetDefaultPropertyIndex( name );
364   }
365   return index;
366 }
367
368 void ImageActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
369 {
370   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
371   {
372     RenderableActor::SetDefaultProperty( index, propertyValue );
373   }
374   else
375   {
376     switch(index)
377     {
378       case Dali::ImageActor::Property::PIXEL_AREA:
379       {
380         SetPixelArea(propertyValue.Get<Rect<int> >());
381         break;
382       }
383       case Dali::ImageActor::Property::STYLE:
384       {
385         SetStyle( StyleEnum( propertyValue.Get<std::string>() ) );
386         break;
387       }
388       case Dali::ImageActor::Property::BORDER:
389       {
390         SetNinePatchBorder( propertyValue.Get<Vector4>(), true /*in pixels*/ );
391         break;
392       }
393       case Dali::ImageActor::Property::IMAGE:
394       {
395         Dali::Image img = Scripting::NewImage( propertyValue );
396         if(img)
397         {
398           ImagePtr image( &GetImplementation(img) );
399           SetImage( image );
400         }
401         else
402         {
403           DALI_LOG_WARNING("Cannot create image from property value\n");
404         }
405         break;
406       }
407       default:
408       {
409         DALI_LOG_WARNING("Unknown property (%d)\n", index);
410         break;
411       }
412     } // switch(index)
413
414   } // else
415 }
416
417 Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const
418 {
419   Property::Value ret;
420   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
421   {
422     ret = RenderableActor::GetDefaultProperty( index );
423   }
424   else
425   {
426     switch( index )
427     {
428       case Dali::ImageActor::Property::PIXEL_AREA:
429       {
430         Rect<int> r = GetPixelArea();
431         ret = r;
432         break;
433       }
434       case Dali::ImageActor::Property::STYLE:
435       {
436         ret = StyleString( GetStyle() );
437         break;
438       }
439       case Dali::ImageActor::Property::BORDER:
440       {
441         ret = GetNinePatchBorder();
442         break;
443       }
444       case Dali::ImageActor::Property::IMAGE:
445       {
446         Property::Map map;
447         Scripting::CreatePropertyMap( Dali::Image( mImageAttachment->GetImage().Get() ), map );
448         ret = Property::Value( map );
449         break;
450       }
451       default:
452       {
453         DALI_LOG_WARNING( "Unknown property (%d)\n", index );
454         break;
455       }
456     } // switch(index)
457   }
458
459   return ret;
460 }
461
462
463 void ImageActor::SetSortModifier(float modifier)
464 {
465   mImageAttachment->SetSortModifier(modifier);
466 }
467
468 float ImageActor::GetSortModifier() const
469 {
470   return mImageAttachment->GetSortModifier();
471 }
472
473 void ImageActor::SetCullFace(CullFaceMode mode)
474 {
475   mImageAttachment->SetCullFace( mode );
476 }
477
478 CullFaceMode ImageActor::GetCullFace() const
479 {
480   return mImageAttachment->GetCullFace();
481 }
482
483 void ImageActor::SetBlendMode( BlendingMode::Type mode )
484 {
485   mImageAttachment->SetBlendMode( mode );
486 }
487
488 BlendingMode::Type ImageActor::GetBlendMode() const
489 {
490   return mImageAttachment->GetBlendMode();
491 }
492
493 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgba,   BlendingFactor::Type destFactorRgba )
494 {
495   mImageAttachment->SetBlendFunc( srcFactorRgba, destFactorRgba, srcFactorRgba, destFactorRgba );
496 }
497
498 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
499                                BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha )
500 {
501   mImageAttachment->SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
502 }
503
504 void ImageActor::GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
505                                     BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const
506 {
507   mImageAttachment->GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
508 }
509
510 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgba )
511 {
512   mImageAttachment->SetBlendEquation( equationRgba, equationRgba );
513 }
514
515 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha )
516 {
517   mImageAttachment->SetBlendEquation( equationRgb, equationAlpha );
518 }
519
520 void ImageActor::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const
521 {
522   mImageAttachment->GetBlendEquation( equationRgb, equationAlpha );
523 }
524
525 void ImageActor::SetBlendColor( const Vector4& color )
526 {
527   mImageAttachment->SetBlendColor( color );
528 }
529
530 const Vector4& ImageActor::GetBlendColor() const
531 {
532   return mImageAttachment->GetBlendColor();
533 }
534
535 void ImageActor::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter )
536 {
537   mImageAttachment->SetFilterMode( minFilter, magFilter );
538 }
539
540 void ImageActor::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const
541 {
542   return mImageAttachment->GetFilterMode( minFilter, magFilter );
543 }
544
545 void ImageActor::SetShaderEffect(ShaderEffect& effect)
546 {
547   mImageAttachment->SetShaderEffect( effect );
548 }
549
550 ShaderEffectPtr ImageActor::GetShaderEffect() const
551 {
552   return mImageAttachment->GetShaderEffect();
553 }
554
555 void ImageActor::RemoveShaderEffect()
556 {
557   return mImageAttachment->RemoveShaderEffect();
558 }
559
560
561 } // namespace Internal
562
563 } // namespace Dali