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 <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>
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 )
50 return Dali::ImageActor::New();
53 TypeRegistration mType( typeid( Dali::ImageActor ), typeid( Dali::RenderableActor ), Create );
55 ImageActor::Style StyleEnum(const std::string &s)
57 if(s == "STYLE_NINE_PATCH")
59 return Dali::ImageActor::STYLE_NINE_PATCH;
61 else if(s == "STYLE_NINE_PATCH_NO_CENTER")
63 return Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER;
65 else // if(s == "QUAD")
67 return Dali::ImageActor::STYLE_QUAD;
71 std::string StyleString(const ImageActor::Style style)
73 if(style == Dali::ImageActor::STYLE_NINE_PATCH)
75 return "STYLE_NINE_PATCH";
77 else if(style == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER)
79 return "STYLE_NINE_PATCH_NO_CENTER";
81 else // if(s == "QUAD")
88 ImageActorPtr ImageActor::New()
90 ImageActorPtr actor( new ImageActor );
92 // Second-phase construction of base class
95 // Create the attachment
96 actor->mImageAttachment = ImageAttachment::New( actor->GetEventThreadServices(), *actor->mNode );
97 actor->Attach( *actor->mImageAttachment );
102 void ImageActor::OnInitialize()
104 SetResizePolicy( USE_NATURAL_SIZE, ALL_DIMENSIONS );
107 void ImageActor::SetImage( ImagePtr& image )
109 ImagePtr currentImage = mImageAttachment->GetImage();
110 // early exit if it's the same image as we already have
111 if ( currentImage == image )
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
121 // Automatically convert nine-patch images to cropped bitmap
122 NinePatchImage* ninePatchImage = NinePatchImage::DownCast( image.Get() );
125 newImage = ninePatchImage->CreateCroppedBufferImage();
126 SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
127 SetNinePatchBorder( ninePatchImage->GetStretchBorders(), true );
130 // set the actual image (normal or 9 patch) and natural size based on that
131 mImageAttachment->SetImage( newImage );
135 ImagePtr ImageActor::GetImage()
137 return mImageAttachment->GetImage();
140 void ImageActor::SetToNaturalSize()
142 mUsingNaturalSize = true;
147 void ImageActor::SetPixelArea( const PixelArea& pixelArea )
149 mImageAttachment->SetPixelArea( pixelArea );
154 const ImageActor::PixelArea& ImageActor::GetPixelArea() const
156 return mImageAttachment->GetPixelArea();
159 bool ImageActor::IsPixelAreaSet() const
161 return mImageAttachment->IsPixelAreaSet();
164 void ImageActor::ClearPixelArea()
166 mImageAttachment->ClearPixelArea();
168 if( mUsingNaturalSize )
170 ImagePtr image = mImageAttachment->GetImage();
173 mInternalSetSize = true;
174 SetSize( image->GetNaturalSize() );
175 SetPreferredSize( GetTargetSize().GetVectorXY() );
176 mInternalSetSize = false;
181 void ImageActor::SetStyle( Style style )
183 mImageAttachment->SetStyle( style );
186 ImageActor::Style ImageActor::GetStyle() const
188 return mImageAttachment->GetStyle();
191 void ImageActor::SetNinePatchBorder( const Vector4& border, bool inPixels )
193 mImageAttachment->SetNinePatchBorder( border, inPixels );
196 Vector4 ImageActor::GetNinePatchBorder() const
198 return mImageAttachment->GetNinePatchBorder();
201 ImageAttachment& ImageActor::GetImageAttachment()
203 return *mImageAttachment;
206 RenderableAttachment& ImageActor::GetRenderableAttachment() const
208 DALI_ASSERT_DEBUG( mImageAttachment && "ImageAttachment missing from ImageActor" );
209 return *mImageAttachment;
212 ImageActor::ImageActor()
214 mUsingNaturalSize(true),
215 mInternalSetSize(false)
217 // Size negotiate disabled by default, so turn it on for this actor
218 SetRelayoutEnabled( true );
221 ImageActor::~ImageActor()
225 void ImageActor::SetNaturalSize()
227 if( mUsingNaturalSize )
229 mInternalSetSize = true;
230 SetSize( CalculateNaturalSize() );
231 SetPreferredSize( GetTargetSize().GetVectorXY() );
232 mInternalSetSize = false;
236 Vector3 ImageActor::GetNaturalSize() const
238 Vector2 naturalSize( CalculateNaturalSize() );
239 return Vector3( naturalSize.width, naturalSize.height, CalculateSizeZ( naturalSize ) );
242 Vector2 ImageActor::CalculateNaturalSize() const
244 // if no image then natural size is 0
245 Vector2 size( 0.0f, 0.0f );
247 ImagePtr image = mImageAttachment->GetImage();
250 if( IsPixelAreaSet() )
252 PixelArea area(GetPixelArea());
253 size.width = area.width;
254 size.height = area.height;
258 size = image->GetNaturalSize();
265 void ImageActor::OnSizeSet( const Vector3& targetSize )
267 if( !mInternalSetSize )
269 mUsingNaturalSize = false;
273 void ImageActor::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
275 mUsingNaturalSize = false;
278 void ImageActor::OnStageConnectionInternal()
282 void ImageActor::OnStageDisconnectionInternal()
286 unsigned int ImageActor::GetDefaultPropertyCount() const
288 return RenderableActor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
291 void ImageActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
293 RenderableActor::GetDefaultPropertyIndices( indices ); // RenderableActor class properties
295 indices.reserve( indices.size() + DEFAULT_PROPERTY_COUNT );
297 int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
298 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
300 indices.push_back( index );
304 bool ImageActor::IsDefaultPropertyWritable( Property::Index index ) const
306 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
308 return RenderableActor::IsDefaultPropertyWritable(index);
311 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
312 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
314 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
320 bool ImageActor::IsDefaultPropertyAnimatable( Property::Index index ) const
322 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
324 return RenderableActor::IsDefaultPropertyAnimatable( index );
327 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
328 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
330 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
336 bool ImageActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
338 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
340 return RenderableActor::IsDefaultPropertyAConstraintInput( index );
343 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
344 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
346 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
352 Property::Type ImageActor::GetDefaultPropertyType( Property::Index index ) const
354 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
356 return RenderableActor::GetDefaultPropertyType( index );
359 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
360 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
362 return DEFAULT_PROPERTY_DETAILS[index].type;
365 // index out-of-bounds
366 return Property::NONE;
369 const char* ImageActor::GetDefaultPropertyName( Property::Index index ) const
371 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
373 return RenderableActor::GetDefaultPropertyName(index);
376 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
377 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
379 return DEFAULT_PROPERTY_DETAILS[index].name;
382 // index out-of-bounds
386 Property::Index ImageActor::GetDefaultPropertyIndex(const std::string& name) const
388 Property::Index index = Property::INVALID_INDEX;
390 // Look for name in default properties
391 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
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
396 index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
401 // If not found, check in base class
402 if( Property::INVALID_INDEX == index )
404 index = RenderableActor::GetDefaultPropertyIndex( name );
409 void ImageActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
411 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
413 RenderableActor::SetDefaultProperty( index, propertyValue );
419 case Dali::ImageActor::Property::PIXEL_AREA:
421 SetPixelArea(propertyValue.Get<Rect<int> >());
424 case Dali::ImageActor::Property::STYLE:
426 SetStyle( StyleEnum( propertyValue.Get<std::string>() ) );
429 case Dali::ImageActor::Property::BORDER:
431 SetNinePatchBorder( propertyValue.Get<Vector4>(), true /*in pixels*/ );
434 case Dali::ImageActor::Property::IMAGE:
436 Dali::Image img = Scripting::NewImage( propertyValue );
439 ImagePtr image( &GetImplementation(img) );
444 DALI_LOG_WARNING("Cannot create image from property value\n");
450 DALI_LOG_WARNING("Unknown property (%d)\n", index);
458 Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const
461 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
463 ret = RenderableActor::GetDefaultProperty( index );
469 case Dali::ImageActor::Property::PIXEL_AREA:
471 Rect<int> r = GetPixelArea();
475 case Dali::ImageActor::Property::STYLE:
477 ret = StyleString( GetStyle() );
480 case Dali::ImageActor::Property::BORDER:
482 ret = GetNinePatchBorder();
485 case Dali::ImageActor::Property::IMAGE:
488 Scripting::CreatePropertyMap( Dali::Image( mImageAttachment->GetImage().Get() ), map );
489 ret = Property::Value( map );
494 DALI_LOG_WARNING( "Unknown property (%d)\n", index );
504 void ImageActor::SetSortModifier(float modifier)
506 mImageAttachment->SetSortModifier(modifier);
509 float ImageActor::GetSortModifier() const
511 return mImageAttachment->GetSortModifier();
514 void ImageActor::SetCullFace(CullFaceMode mode)
516 mImageAttachment->SetCullFace( mode );
519 CullFaceMode ImageActor::GetCullFace() const
521 return mImageAttachment->GetCullFace();
524 void ImageActor::SetBlendMode( BlendingMode::Type mode )
526 mImageAttachment->SetBlendMode( mode );
529 BlendingMode::Type ImageActor::GetBlendMode() const
531 return mImageAttachment->GetBlendMode();
534 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba )
536 mImageAttachment->SetBlendFunc( srcFactorRgba, destFactorRgba, srcFactorRgba, destFactorRgba );
539 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgb, BlendingFactor::Type destFactorRgb,
540 BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha )
542 mImageAttachment->SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
545 void ImageActor::GetBlendFunc( BlendingFactor::Type& srcFactorRgb, BlendingFactor::Type& destFactorRgb,
546 BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const
548 mImageAttachment->GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
551 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgba )
553 mImageAttachment->SetBlendEquation( equationRgba, equationRgba );
556 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha )
558 mImageAttachment->SetBlendEquation( equationRgb, equationAlpha );
561 void ImageActor::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const
563 mImageAttachment->GetBlendEquation( equationRgb, equationAlpha );
566 void ImageActor::SetBlendColor( const Vector4& color )
568 mImageAttachment->SetBlendColor( color );
571 const Vector4& ImageActor::GetBlendColor() const
573 return mImageAttachment->GetBlendColor();
576 void ImageActor::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter )
578 mImageAttachment->SetFilterMode( minFilter, magFilter );
581 void ImageActor::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const
583 return mImageAttachment->GetFilterMode( minFilter, magFilter );
586 void ImageActor::SetShaderEffect(ShaderEffect& effect)
588 mImageAttachment->SetShaderEffect( effect );
591 ShaderEffectPtr ImageActor::GetShaderEffect() const
593 return mImageAttachment->GetShaderEffect();
596 void ImageActor::RemoveShaderEffect()
598 return mImageAttachment->RemoveShaderEffect();
602 } // namespace Internal