Remove last reference to boost in dali-core
[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/public-api/scripting/scripting.h>
27 #include <dali/internal/event/common/property-helper.h>
28 #include <dali/internal/event/images/image-connector.h>
29 #include <dali/internal/event/images/nine-patch-image-impl.h>
30
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 namespace
38 {
39
40 // Properties
41
42 //              Name           Type   writable animatable constraint-input  enum for index-checking
43 DALI_PROPERTY_TABLE_BEGIN
44 DALI_PROPERTY( "pixel-area",   RECTANGLE, true,    false,   true,    Dali::ImageActor::Property::PIXEL_AREA )
45 DALI_PROPERTY( "style",        STRING,    true,    false,   true,    Dali::ImageActor::Property::STYLE      )
46 DALI_PROPERTY( "border",       VECTOR4,   true,    false,   true,    Dali::ImageActor::Property::BORDER     )
47 DALI_PROPERTY( "image",        MAP,       true,    false,   false,   Dali::ImageActor::Property::IMAGE      )
48 DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX )
49
50 BaseHandle Create()
51 {
52   return Dali::ImageActor::New();
53 }
54
55 TypeRegistration mType( typeid( Dali::ImageActor ), typeid( Dali::RenderableActor ), Create );
56
57 ImageActor::Style StyleEnum(const std::string &s)
58 {
59   if(s == "STYLE_NINE_PATCH")
60   {
61     return Dali::ImageActor::STYLE_NINE_PATCH;
62   }
63   else if(s == "STYLE_NINE_PATCH_NO_CENTER")
64   {
65     return Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER;
66   }
67   else // if(s == "QUAD")
68   {
69     return Dali::ImageActor::STYLE_QUAD;
70   }
71 }
72
73 std::string StyleString(const ImageActor::Style style)
74 {
75   if(style == Dali::ImageActor::STYLE_NINE_PATCH)
76   {
77     return "STYLE_NINE_PATCH";
78   }
79   else if(style == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER)
80   {
81     return "STYLE_NINE_PATCH_NO_CENTER";
82   }
83   else // if(s == "QUAD")
84   {
85     return "STYLE_QUAD";
86   }
87 }
88 }
89
90 ImageActorPtr ImageActor::New()
91 {
92   ImageActorPtr actor( new ImageActor );
93
94   // Second-phase construction of base class
95   actor->Initialize();
96
97   // Create the attachment
98   actor->mImageAttachment = ImageAttachment::New( actor->GetEventThreadServices(), *actor->mNode );
99   actor->Attach( *actor->mImageAttachment );
100
101   return actor;
102 }
103
104 void ImageActor::OnInitialize()
105 {
106   SetResizePolicy( USE_NATURAL_SIZE, ALL_DIMENSIONS );
107 }
108
109 void ImageActor::SetImage( ImagePtr& image )
110 {
111   ImagePtr currentImage = mImageAttachment->GetImage();
112   // early exit if it's the same image as we already have
113   if ( currentImage == image )
114   {
115     return;
116   }
117
118   // NOTE! image might be pointing to NULL, which is fine as in that case app wants to just remove the image
119   ImagePtr newImage( image );
120   // if image is not NULL, check for 9 patch
121   if( newImage )
122   {
123     // Automatically convert nine-patch images to cropped bitmap
124     NinePatchImage* ninePatchImage = NinePatchImage::DownCast( image.Get() );
125     if( ninePatchImage )
126     {
127       newImage = ninePatchImage->CreateCroppedBufferImage();
128       SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
129       SetNinePatchBorder( ninePatchImage->GetStretchBorders(), true );
130     }
131   }
132   // set the actual image (normal or 9 patch) and natural size based on that
133   mImageAttachment->SetImage( newImage );
134   SetNaturalSize();
135 }
136
137 ImagePtr ImageActor::GetImage()
138 {
139   return mImageAttachment->GetImage();
140 }
141
142 void ImageActor::SetToNaturalSize()
143 {
144   mUsingNaturalSize = true;
145
146   SetNaturalSize();
147 }
148
149 void ImageActor::SetPixelArea( const PixelArea& pixelArea )
150 {
151   mImageAttachment->SetPixelArea( pixelArea );
152
153   SetNaturalSize();
154 }
155
156 const ImageActor::PixelArea& ImageActor::GetPixelArea() const
157 {
158   return mImageAttachment->GetPixelArea();
159 }
160
161 bool ImageActor::IsPixelAreaSet() const
162 {
163   return mImageAttachment->IsPixelAreaSet();
164 }
165
166 void ImageActor::ClearPixelArea()
167 {
168   mImageAttachment->ClearPixelArea();
169
170   if( mUsingNaturalSize )
171   {
172     ImagePtr image = mImageAttachment->GetImage();
173     if( image )
174     {
175       mInternalSetSize = true;
176       SetSizeInternal( image->GetNaturalSize() );
177       mInternalSetSize = false;
178     }
179   }
180 }
181
182 void ImageActor::SetStyle( Style style )
183 {
184   mImageAttachment->SetStyle( style );
185 }
186
187 ImageActor::Style ImageActor::GetStyle() const
188 {
189   return mImageAttachment->GetStyle();
190 }
191
192 void ImageActor::SetNinePatchBorder( const Vector4& border, bool inPixels )
193 {
194   mImageAttachment->SetNinePatchBorder( border, inPixels );
195 }
196
197 Vector4 ImageActor::GetNinePatchBorder() const
198 {
199   return mImageAttachment->GetNinePatchBorder();
200 }
201
202 ImageAttachment& ImageActor::GetImageAttachment()
203 {
204   return *mImageAttachment;
205 }
206
207 RenderableAttachment& ImageActor::GetRenderableAttachment() const
208 {
209   DALI_ASSERT_DEBUG( mImageAttachment && "ImageAttachment missing from ImageActor" );
210   return *mImageAttachment;
211 }
212
213 ImageActor::ImageActor()
214 : RenderableActor(),
215   mUsingNaturalSize(true),
216   mInternalSetSize(false)
217 {
218   // Size negotiate disabled by default, so turn it on for this actor
219   SetRelayoutEnabled( true );
220 }
221
222 ImageActor::~ImageActor()
223 {
224 }
225
226 void ImageActor::SetNaturalSize()
227 {
228   if( mUsingNaturalSize )
229   {
230     mInternalSetSize = true;
231     SetSizeInternal( CalculateNaturalSize() );
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 } // namespace Internal
504
505 } // namespace Dali