2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/actors/image-actor-impl.h>
22 #include <cstring> // for strcmp
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>
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 )
53 return Dali::ImageActor::New();
56 TypeRegistration mType( typeid( Dali::ImageActor ), typeid( Dali::Actor ), Create );
58 ImageActor::Style StyleEnum(const std::string &s)
60 if(s == "STYLE_NINE_PATCH")
62 return Dali::ImageActor::STYLE_NINE_PATCH;
64 else if(s == "STYLE_NINE_PATCH_NO_CENTER")
66 return Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER;
68 else // if(s == "QUAD")
70 return Dali::ImageActor::STYLE_QUAD;
74 std::string StyleString(const ImageActor::Style style)
76 if(style == Dali::ImageActor::STYLE_NINE_PATCH)
78 return "STYLE_NINE_PATCH";
80 else if(style == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER)
82 return "STYLE_NINE_PATCH_NO_CENTER";
84 else // if(s == "QUAD")
91 ImageActorPtr ImageActor::New()
93 ImageActorPtr actor( new ImageActor );
95 // Second-phase construction of base class
98 // Create the attachment
99 actor->mImageAttachment = ImageAttachment::New( actor->GetEventThreadServices(), *actor->mNode );
100 actor->Attach( *actor->mImageAttachment );
105 void ImageActor::OnInitialize()
107 // TODO: Remove this, at the moment its needed for size negotiation to work
108 SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
111 void ImageActor::SetImage( ImagePtr& image )
113 ImagePtr currentImage = mImageAttachment->GetImage();
114 // early exit if it's the same image as we already have
115 if ( currentImage == image )
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
125 // Automatically convert nine-patch images to cropped bitmap
126 NinePatchImage* ninePatchImage = NinePatchImage::DownCast( image.Get() );
129 newImage = ninePatchImage->CreateCroppedBufferImage();
130 SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
132 const NinePatchImage::StretchRanges& stretchPixelsX = ninePatchImage->GetStretchPixelsX();
133 const NinePatchImage::StretchRanges& stretchPixelsY = ninePatchImage->GetStretchPixelsY();
135 if( stretchPixelsX.Size() > 0 && stretchPixelsY.Size() > 0 )
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;
144 SetNinePatchBorder( border, true );
148 // set the actual image (normal or 9 patch) and natural size based on that
149 mImageAttachment->SetImage( newImage );
154 ImagePtr ImageActor::GetImage()
156 return mImageAttachment->GetImage();
159 void ImageActor::SetPixelArea( const PixelArea& pixelArea )
161 mImageAttachment->SetPixelArea( pixelArea );
166 const ImageActor::PixelArea& ImageActor::GetPixelArea() const
168 return mImageAttachment->GetPixelArea();
171 bool ImageActor::IsPixelAreaSet() const
173 return mImageAttachment->IsPixelAreaSet();
176 void ImageActor::ClearPixelArea()
178 mImageAttachment->ClearPixelArea();
183 void ImageActor::SetStyle( Style style )
185 mImageAttachment->SetStyle( style );
188 ImageActor::Style ImageActor::GetStyle() const
190 return mImageAttachment->GetStyle();
193 void ImageActor::SetNinePatchBorder( const Vector4& border, bool inPixels )
195 mImageAttachment->SetNinePatchBorder( border, inPixels );
198 Vector4 ImageActor::GetNinePatchBorder() const
200 return mImageAttachment->GetNinePatchBorder();
203 ImageAttachment& ImageActor::GetImageAttachment()
205 return *mImageAttachment;
208 RenderableAttachment& ImageActor::GetRenderableAttachment() const
210 DALI_ASSERT_DEBUG( mImageAttachment && "ImageAttachment missing from ImageActor" );
211 return *mImageAttachment;
214 ImageActor::ImageActor()
215 : Actor( Actor::RENDERABLE )
219 ImageActor::~ImageActor()
223 Vector3 ImageActor::GetNaturalSize() const
225 Vector2 naturalSize( CalculateNaturalSize() );
226 return Vector3( naturalSize.width, naturalSize.height, 0.f );
229 Vector2 ImageActor::CalculateNaturalSize() const
231 // if no image then natural size is 0
232 Vector2 size( 0.0f, 0.0f );
234 ImagePtr image = mImageAttachment->GetImage();
237 if( IsPixelAreaSet() )
239 PixelArea area(GetPixelArea());
240 size.width = area.width;
241 size.height = area.height;
245 size = image->GetNaturalSize();
252 void ImageActor::OnStageConnectionInternal()
256 void ImageActor::OnStageDisconnectionInternal()
260 unsigned int ImageActor::GetDefaultPropertyCount() const
262 return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
265 void ImageActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
267 Actor::GetDefaultPropertyIndices( indices ); // Actor class properties
269 indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
271 int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
272 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
274 indices.PushBack( index );
278 bool ImageActor::IsDefaultPropertyWritable( Property::Index index ) const
280 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
282 return Actor::IsDefaultPropertyWritable(index);
285 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
286 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
288 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
294 bool ImageActor::IsDefaultPropertyAnimatable( Property::Index index ) const
296 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
298 return Actor::IsDefaultPropertyAnimatable( index );
301 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
302 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
304 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
310 bool ImageActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
312 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
314 return Actor::IsDefaultPropertyAConstraintInput( index );
317 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
318 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
320 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
326 Property::Type ImageActor::GetDefaultPropertyType( Property::Index index ) const
328 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
330 return Actor::GetDefaultPropertyType( index );
333 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
334 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
336 return DEFAULT_PROPERTY_DETAILS[index].type;
339 // index out-of-bounds
340 return Property::NONE;
343 const char* ImageActor::GetDefaultPropertyName( Property::Index index ) const
345 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
347 return Actor::GetDefaultPropertyName(index);
350 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
351 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
353 return DEFAULT_PROPERTY_DETAILS[index].name;
356 // index out-of-bounds
360 Property::Index ImageActor::GetDefaultPropertyIndex(const std::string& name) const
362 Property::Index index = Property::INVALID_INDEX;
364 // Look for name in default properties
365 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
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
370 index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
375 // If not found, check in base class
376 if( Property::INVALID_INDEX == index )
378 index = Actor::GetDefaultPropertyIndex( name );
383 void ImageActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
385 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
387 Actor::SetDefaultProperty( index, propertyValue );
393 case Dali::ImageActor::Property::PIXEL_AREA:
395 SetPixelArea(propertyValue.Get<Rect<int> >());
398 case Dali::ImageActor::Property::STYLE:
400 SetStyle( StyleEnum( propertyValue.Get<std::string>() ) );
403 case Dali::ImageActor::Property::BORDER:
405 SetNinePatchBorder( propertyValue.Get<Vector4>(), true /*in pixels*/ );
408 case Dali::ImageActor::Property::IMAGE:
410 Dali::Image img = Scripting::NewImage( propertyValue );
413 ImagePtr image( &GetImplementation(img) );
418 DALI_LOG_WARNING("Cannot create image from property value\n");
424 DALI_LOG_WARNING("Unknown property (%d)\n", index);
432 Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const
435 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
437 ret = Actor::GetDefaultProperty( index );
443 case Dali::ImageActor::Property::PIXEL_AREA:
445 Rect<int> r = GetPixelArea();
449 case Dali::ImageActor::Property::STYLE:
451 ret = StyleString( GetStyle() );
454 case Dali::ImageActor::Property::BORDER:
456 ret = GetNinePatchBorder();
459 case Dali::ImageActor::Property::IMAGE:
462 Scripting::CreatePropertyMap( Dali::Image( mImageAttachment->GetImage().Get() ), map );
463 ret = Property::Value( map );
468 DALI_LOG_WARNING( "Unknown property (%d)\n", index );
478 void ImageActor::SetSortModifier(float modifier)
480 mImageAttachment->SetSortModifier( modifier );
483 float ImageActor::GetSortModifier() const
485 return mImageAttachment->GetSortModifier();
488 void ImageActor::SetDepthIndex( int depthIndex )
490 mImageAttachment->SetSortModifier( depthIndex );
493 int ImageActor::GetDepthIndex() const
495 return static_cast< int >( mImageAttachment->GetSortModifier() );
498 void ImageActor::SetCullFace(CullFaceMode mode)
500 mImageAttachment->SetCullFace( mode );
503 CullFaceMode ImageActor::GetCullFace() const
505 return mImageAttachment->GetCullFace();
508 void ImageActor::SetBlendMode( BlendingMode::Type mode )
510 mImageAttachment->SetBlendMode( mode );
513 BlendingMode::Type ImageActor::GetBlendMode() const
515 return mImageAttachment->GetBlendMode();
518 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba )
520 mImageAttachment->SetBlendFunc( srcFactorRgba, destFactorRgba, srcFactorRgba, destFactorRgba );
523 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgb, BlendingFactor::Type destFactorRgb,
524 BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha )
526 mImageAttachment->SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
529 void ImageActor::GetBlendFunc( BlendingFactor::Type& srcFactorRgb, BlendingFactor::Type& destFactorRgb,
530 BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const
532 mImageAttachment->GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
535 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgba )
537 mImageAttachment->SetBlendEquation( equationRgba, equationRgba );
540 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha )
542 mImageAttachment->SetBlendEquation( equationRgb, equationAlpha );
545 void ImageActor::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const
547 mImageAttachment->GetBlendEquation( equationRgb, equationAlpha );
550 void ImageActor::SetBlendColor( const Vector4& color )
552 mImageAttachment->SetBlendColor( color );
555 const Vector4& ImageActor::GetBlendColor() const
557 return mImageAttachment->GetBlendColor();
560 void ImageActor::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter )
562 mImageAttachment->SetFilterMode( minFilter, magFilter );
565 void ImageActor::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const
567 return mImageAttachment->GetFilterMode( minFilter, magFilter );
570 void ImageActor::SetShaderEffect(ShaderEffect& effect)
572 mImageAttachment->SetShaderEffect( effect );
575 ShaderEffectPtr ImageActor::GetShaderEffect() const
577 return mImageAttachment->GetShaderEffect();
580 void ImageActor::RemoveShaderEffect()
582 return mImageAttachment->RemoveShaderEffect();
586 } // namespace Internal