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