Changed all property & signal names to lowerCamelCase
[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( "pixelArea",    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::Actor ), 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   // TODO: Remove this, at the moment its needed for size negotiation to work
108   SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
109 }
110
111 void ImageActor::SetImage( ImagePtr& image )
112 {
113   ImagePtr currentImage = mImageAttachment->GetImage();
114   // early exit if it's the same image as we already have
115   if ( currentImage == image )
116   {
117     return;
118   }
119
120   // NOTE! image might be pointing to NULL, which is fine as in that case app wants to just remove the image
121   ImagePtr newImage( image );
122   // if image is not NULL, check for 9 patch
123   if( newImage )
124   {
125     // Automatically convert nine-patch images to cropped bitmap
126     NinePatchImage* ninePatchImage = NinePatchImage::DownCast( image.Get() );
127     if( ninePatchImage )
128     {
129       newImage = ninePatchImage->CreateCroppedBufferImage();
130       SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
131
132       const NinePatchImage::StretchRanges& stretchPixelsX = ninePatchImage->GetStretchPixelsX();
133       const NinePatchImage::StretchRanges& stretchPixelsY = ninePatchImage->GetStretchPixelsY();
134
135       if( stretchPixelsX.Size() > 0 && stretchPixelsY.Size() > 0 )
136       {
137         Vector4 border;
138         //The NinePatchImage stretch pixels are in the cropped image space, inset by 1 to get it to uncropped image space
139         border.x = stretchPixelsX[ 0 ].GetX() + 1;
140         border.y = stretchPixelsY[ 0 ].GetX() + 1;
141         border.z = image->GetWidth() - stretchPixelsX[ 0 ].GetY() - 1;
142         border.w = image->GetHeight() - stretchPixelsY[ 0 ].GetY() - 1;
143
144         SetNinePatchBorder( border, true );
145       }
146     }
147   }
148   // set the actual image (normal or 9 patch) and natural size based on that
149   mImageAttachment->SetImage( newImage );
150
151   RelayoutRequest();
152 }
153
154 ImagePtr ImageActor::GetImage()
155 {
156   return mImageAttachment->GetImage();
157 }
158
159 void ImageActor::SetPixelArea( const PixelArea& pixelArea )
160 {
161   mImageAttachment->SetPixelArea( pixelArea );
162
163   RelayoutRequest();
164 }
165
166 const ImageActor::PixelArea& ImageActor::GetPixelArea() const
167 {
168   return mImageAttachment->GetPixelArea();
169 }
170
171 bool ImageActor::IsPixelAreaSet() const
172 {
173   return mImageAttachment->IsPixelAreaSet();
174 }
175
176 void ImageActor::ClearPixelArea()
177 {
178   mImageAttachment->ClearPixelArea();
179
180   RelayoutRequest();
181 }
182
183 void ImageActor::SetStyle( Style style )
184 {
185   mImageAttachment->SetStyle( style );
186 }
187
188 ImageActor::Style ImageActor::GetStyle() const
189 {
190   return mImageAttachment->GetStyle();
191 }
192
193 void ImageActor::SetNinePatchBorder( const Vector4& border, bool inPixels )
194 {
195   mImageAttachment->SetNinePatchBorder( border, inPixels );
196 }
197
198 Vector4 ImageActor::GetNinePatchBorder() const
199 {
200   return mImageAttachment->GetNinePatchBorder();
201 }
202
203 ImageAttachment& ImageActor::GetImageAttachment()
204 {
205   return *mImageAttachment;
206 }
207
208 RenderableAttachment& ImageActor::GetRenderableAttachment() const
209 {
210   DALI_ASSERT_DEBUG( mImageAttachment && "ImageAttachment missing from ImageActor" );
211   return *mImageAttachment;
212 }
213
214 ImageActor::ImageActor()
215 : Actor( Actor::RENDERABLE )
216 {
217 }
218
219 ImageActor::~ImageActor()
220 {
221 }
222
223 Vector3 ImageActor::GetNaturalSize() const
224 {
225   Vector2 naturalSize( CalculateNaturalSize() );
226   return Vector3( naturalSize.width, naturalSize.height, 0.f );
227 }
228
229 Vector2 ImageActor::CalculateNaturalSize() const
230 {
231   // if no image then natural size is 0
232   Vector2 size( 0.0f, 0.0f );
233
234   ImagePtr image = mImageAttachment->GetImage();
235   if( image )
236   {
237     if( IsPixelAreaSet() )
238     {
239       PixelArea area(GetPixelArea());
240       size.width = area.width;
241       size.height = area.height;
242     }
243     else
244     {
245       size = image->GetNaturalSize();
246     }
247   }
248
249   return size;
250 }
251
252 void ImageActor::OnStageConnectionInternal()
253 {
254 }
255
256 void ImageActor::OnStageDisconnectionInternal()
257 {
258 }
259
260 unsigned int ImageActor::GetDefaultPropertyCount() const
261 {
262   return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
263 }
264
265 void ImageActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
266 {
267   Actor::GetDefaultPropertyIndices( indices ); // Actor class properties
268
269   indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
270
271   int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
272   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
273   {
274     indices.PushBack( index );
275   }
276 }
277
278 bool ImageActor::IsDefaultPropertyWritable( Property::Index index ) const
279 {
280   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
281   {
282     return Actor::IsDefaultPropertyWritable(index);
283   }
284
285   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
286   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
287   {
288     return DEFAULT_PROPERTY_DETAILS[ index ].writable;
289   }
290
291   return false;
292 }
293
294 bool ImageActor::IsDefaultPropertyAnimatable( Property::Index index ) const
295 {
296   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
297   {
298     return Actor::IsDefaultPropertyAnimatable( index );
299   }
300
301   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
302   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
303   {
304     return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
305   }
306
307   return false;
308 }
309
310 bool ImageActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
311 {
312   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
313   {
314     return Actor::IsDefaultPropertyAConstraintInput( index );
315   }
316
317   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
318   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
319   {
320     return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
321   }
322
323   return false;
324 }
325
326 Property::Type ImageActor::GetDefaultPropertyType( Property::Index index ) const
327 {
328   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
329   {
330     return Actor::GetDefaultPropertyType( index );
331   }
332
333   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
334   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
335   {
336     return DEFAULT_PROPERTY_DETAILS[index].type;
337   }
338
339   // index out-of-bounds
340   return Property::NONE;
341 }
342
343 const char* ImageActor::GetDefaultPropertyName( Property::Index index ) const
344 {
345   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
346   {
347     return Actor::GetDefaultPropertyName(index);
348   }
349
350   index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
351   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
352   {
353     return DEFAULT_PROPERTY_DETAILS[index].name;
354   }
355
356   // index out-of-bounds
357   return NULL;
358 }
359
360 Property::Index ImageActor::GetDefaultPropertyIndex(const std::string& name) const
361 {
362   Property::Index index = Property::INVALID_INDEX;
363
364   // Look for name in default properties
365   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
366   {
367     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
368     if( 0 == strcmp( name.c_str(), property->name ) ) // Don't want to convert rhs to string
369     {
370       index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
371       break;
372     }
373   }
374
375   // If not found, check in base class
376   if( Property::INVALID_INDEX == index )
377   {
378     index = Actor::GetDefaultPropertyIndex( name );
379   }
380   return index;
381 }
382
383 void ImageActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
384 {
385   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
386   {
387     Actor::SetDefaultProperty( index, propertyValue );
388   }
389   else
390   {
391     switch(index)
392     {
393       case Dali::ImageActor::Property::PIXEL_AREA:
394       {
395         SetPixelArea(propertyValue.Get<Rect<int> >());
396         break;
397       }
398       case Dali::ImageActor::Property::STYLE:
399       {
400         SetStyle( StyleEnum( propertyValue.Get<std::string>() ) );
401         break;
402       }
403       case Dali::ImageActor::Property::BORDER:
404       {
405         SetNinePatchBorder( propertyValue.Get<Vector4>(), true /*in pixels*/ );
406         break;
407       }
408       case Dali::ImageActor::Property::IMAGE:
409       {
410         Dali::Image img = Scripting::NewImage( propertyValue );
411         if(img)
412         {
413           ImagePtr image( &GetImplementation(img) );
414           SetImage( image );
415         }
416         else
417         {
418           DALI_LOG_WARNING("Cannot create image from property value\n");
419         }
420         break;
421       }
422       default:
423       {
424         DALI_LOG_WARNING("Unknown property (%d)\n", index);
425         break;
426       }
427     } // switch(index)
428
429   } // else
430 }
431
432 Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const
433 {
434   Property::Value ret;
435   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
436   {
437     ret = Actor::GetDefaultProperty( index );
438   }
439   else
440   {
441     switch( index )
442     {
443       case Dali::ImageActor::Property::PIXEL_AREA:
444       {
445         Rect<int> r = GetPixelArea();
446         ret = r;
447         break;
448       }
449       case Dali::ImageActor::Property::STYLE:
450       {
451         ret = StyleString( GetStyle() );
452         break;
453       }
454       case Dali::ImageActor::Property::BORDER:
455       {
456         ret = GetNinePatchBorder();
457         break;
458       }
459       case Dali::ImageActor::Property::IMAGE:
460       {
461         Property::Map map;
462         Scripting::CreatePropertyMap( Dali::Image( mImageAttachment->GetImage().Get() ), map );
463         ret = Property::Value( map );
464         break;
465       }
466       default:
467       {
468         DALI_LOG_WARNING( "Unknown property (%d)\n", index );
469         break;
470       }
471     } // switch(index)
472   }
473
474   return ret;
475 }
476
477
478 void ImageActor::SetSortModifier(float modifier)
479 {
480   mImageAttachment->SetSortModifier( modifier );
481 }
482
483 float ImageActor::GetSortModifier() const
484 {
485   return mImageAttachment->GetSortModifier();
486 }
487
488 void ImageActor::SetDepthIndex( int depthIndex )
489 {
490    mImageAttachment->SetSortModifier( depthIndex );
491 }
492
493 int ImageActor::GetDepthIndex() const
494 {
495   return static_cast< int >( mImageAttachment->GetSortModifier() );
496 }
497
498 void ImageActor::SetCullFace(CullFaceMode mode)
499 {
500   mImageAttachment->SetCullFace( mode );
501 }
502
503 CullFaceMode ImageActor::GetCullFace() const
504 {
505   return mImageAttachment->GetCullFace();
506 }
507
508 void ImageActor::SetBlendMode( BlendingMode::Type mode )
509 {
510   mImageAttachment->SetBlendMode( mode );
511 }
512
513 BlendingMode::Type ImageActor::GetBlendMode() const
514 {
515   return mImageAttachment->GetBlendMode();
516 }
517
518 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgba,   BlendingFactor::Type destFactorRgba )
519 {
520   mImageAttachment->SetBlendFunc( srcFactorRgba, destFactorRgba, srcFactorRgba, destFactorRgba );
521 }
522
523 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
524                                BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha )
525 {
526   mImageAttachment->SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
527 }
528
529 void ImageActor::GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
530                                     BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const
531 {
532   mImageAttachment->GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
533 }
534
535 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgba )
536 {
537   mImageAttachment->SetBlendEquation( equationRgba, equationRgba );
538 }
539
540 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha )
541 {
542   mImageAttachment->SetBlendEquation( equationRgb, equationAlpha );
543 }
544
545 void ImageActor::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const
546 {
547   mImageAttachment->GetBlendEquation( equationRgb, equationAlpha );
548 }
549
550 void ImageActor::SetBlendColor( const Vector4& color )
551 {
552   mImageAttachment->SetBlendColor( color );
553 }
554
555 const Vector4& ImageActor::GetBlendColor() const
556 {
557   return mImageAttachment->GetBlendColor();
558 }
559
560 void ImageActor::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter )
561 {
562   mImageAttachment->SetFilterMode( minFilter, magFilter );
563 }
564
565 void ImageActor::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const
566 {
567   return mImageAttachment->GetFilterMode( minFilter, magFilter );
568 }
569
570 void ImageActor::SetShaderEffect(ShaderEffect& effect)
571 {
572   mImageAttachment->SetShaderEffect( effect );
573 }
574
575 ShaderEffectPtr ImageActor::GetShaderEffect() const
576 {
577   return mImageAttachment->GetShaderEffect();
578 }
579
580 void ImageActor::RemoveShaderEffect()
581 {
582   return mImageAttachment->RemoveShaderEffect();
583 }
584
585
586 } // namespace Internal
587
588 } // namespace Dali