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