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