2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
21 #include "super-blur-view-impl.h"
23 namespace //unnamed namespace
29 TypeRegistration mType( typeid(Toolkit::SuperBlurView), typeid(Toolkit::Control), NULL );
31 //Todo: make these properties instead of constants
32 const unsigned int GAUSSIAN_BLUR_DEFAULT_NUM_SAMPLES = 11;
33 const unsigned int GAUSSIAN_BLUR_NUM_SAMPLES_INCREMENTATION = 10;
34 const float GAUSSIAN_BLUR_BELL_CURVE_WIDTH = 4.5f;
35 const float GAUSSIAN_BLUR_BELL_CURVE_WIDTH_INCREMENTATION = 5.f;
36 const Pixel::Format GAUSSIAN_BLUR_RENDER_TARGET_PIXEL_FORMAT = Pixel::RGB888;
37 const float GAUSSIAN_BLUR_DOWNSAMPLE_WIDTH_SCALE = 0.5f;
38 const float GAUSSIAN_BLUR_DOWNSAMPLE_HEIGHT_SCALE = 0.5f;
41 * The constraint is used to blend the group of blurred images continuously with a unified blur strength property value which ranges from zero to one.
43 struct ActorOpacityConstraint
45 ActorOpacityConstraint(int totalImageNum, int currentImageIdx)
47 float rangeLength = 1.f / static_cast<float>( totalImageNum );
48 float index = static_cast<float>( currentImageIdx );
49 mRange = Vector2( index*rangeLength, (index+1.f)*rangeLength );
52 float operator()( float current, const PropertyInput& blurProperty )
54 float blurStrength = blurProperty.GetFloat();
55 if(blurStrength <= mRange.x)
59 else if(blurStrength > mRange.y)
65 return (mRange.y - blurStrength)/(mRange.y-mRange.x);
83 SuperBlurView::SuperBlurView( unsigned int blurLevels )
84 : ControlImpl( false ),
85 mBlurLevels( blurLevels ),
86 mBlurStrengthPropertyIndex(Property::INVALID_INDEX),
87 mResourcesCleared( true ),
88 mTargetSize( Vector2::ZERO )
90 DALI_ASSERT_ALWAYS( mBlurLevels > 0 && " Minimal blur level is one, otherwise no blur is needed" );
91 mGaussianBlurView.resize( blurLevels );
92 mBlurredImage.resize( blurLevels );
93 mImageActors.resize( blurLevels + 1 );
96 SuperBlurView::~SuperBlurView()
100 Toolkit::SuperBlurView SuperBlurView::New( unsigned int blurLevels )
102 //Create the implementation
103 IntrusivePtr<SuperBlurView> superBlurView( new SuperBlurView( blurLevels ) );
105 //Pass ownership to CustomActor via derived handle
106 Toolkit::SuperBlurView handle( *superBlurView );
108 // Second-phase init of the implementation
109 // This can only be done after the CustomActor connection has been made...
110 superBlurView->Initialize();
115 void SuperBlurView::OnInitialize()
117 mBlurStrengthPropertyIndex = Self().RegisterProperty( "BLUR_STRENGTH",0.f );
119 DALI_ASSERT_ALWAYS( mImageActors.size() == mBlurLevels+1 && "must synchronize the ImageActor group if blur levels got changed " );
120 for(unsigned int i=0; i<=mBlurLevels;i++)
122 mImageActors[i] = ImageActor::New( );
123 mImageActors[i].SetParentOrigin( ParentOrigin::CENTER );
124 mImageActors[i].SetZ(-static_cast<float>(i)*0.01f);
125 mImageActors[i].SetColorMode( USE_OWN_MULTIPLY_PARENT_ALPHA );
126 Self().Add( mImageActors[i] );
129 for(unsigned int i=0; i < mBlurLevels; i++)
131 mImageActors[i].ApplyConstraint( Constraint::New<float>( Actor::COLOR_ALPHA, ParentSource( mBlurStrengthPropertyIndex ), ActorOpacityConstraint(mBlurLevels, i) ) );
134 Self().SetSize(Stage::GetCurrent().GetSize());
137 void SuperBlurView::SetImage(Image inputImage)
139 DALI_ASSERT_ALWAYS( mImageActors.size() == mBlurLevels+1 && "must synchronize the ImageActor group if blur levels got changed " );
140 DALI_ASSERT_ALWAYS( mBlurredImage.size() == mBlurLevels && "must synchronize the blurred image group if blur levels got changed " );
144 mImageActors[0].SetImage( inputImage );
146 for(unsigned int i=1; i<=mBlurLevels;i++)
148 mImageActors[i].SetImage( mBlurredImage[i-1] );
151 BlurImage( 0, inputImage);
152 for(unsigned int i=1; i<mBlurLevels;i++)
154 BlurImage( i, mBlurredImage[i-1]);
157 mResourcesCleared = false;
160 Property::Index SuperBlurView::GetBlurStrengthPropertyIndex() const
162 return mBlurStrengthPropertyIndex;
165 void SuperBlurView::SetBlurStrength( float blurStrength )
167 Self().SetProperty(mBlurStrengthPropertyIndex, blurStrength);
170 float SuperBlurView::GetCurrentBlurStrength() const
173 (Self().GetProperty( mBlurStrengthPropertyIndex )).Get(blurStrength);
178 Toolkit::SuperBlurView::SuperBlurViewSignal& SuperBlurView::BlurFinishedSignal()
180 return mBlurFinishedSignal;
183 Image SuperBlurView::GetBlurredImage( unsigned int level )
185 DALI_ASSERT_ALWAYS( level>0 && level<=mBlurLevels );
186 return mBlurredImage[level-1];
189 void SuperBlurView::BlurImage( unsigned int idx, Image image )
191 DALI_ASSERT_ALWAYS( mGaussianBlurView.size()>idx );
192 mGaussianBlurView[idx] = Toolkit::GaussianBlurView::New( GAUSSIAN_BLUR_DEFAULT_NUM_SAMPLES+GAUSSIAN_BLUR_NUM_SAMPLES_INCREMENTATION*idx,
193 GAUSSIAN_BLUR_BELL_CURVE_WIDTH + GAUSSIAN_BLUR_BELL_CURVE_WIDTH_INCREMENTATION*static_cast<float>(idx),
194 GAUSSIAN_BLUR_RENDER_TARGET_PIXEL_FORMAT,
195 GAUSSIAN_BLUR_DOWNSAMPLE_WIDTH_SCALE, GAUSSIAN_BLUR_DOWNSAMPLE_HEIGHT_SCALE, true );
196 mGaussianBlurView[idx].SetParentOrigin(ParentOrigin::CENTER);
197 mGaussianBlurView[idx].SetSize(mTargetSize);
198 mGaussianBlurView[idx].SetUserImageAndOutputRenderTarget( image, mBlurredImage[idx] );
199 if( idx == mBlurLevels-1 )
201 mGaussianBlurView[idx].FinishedSignal().Connect( this, &SuperBlurView::OnBlurViewFinished );
203 Stage::GetCurrent().Add( mGaussianBlurView[idx] );
204 mGaussianBlurView[idx].ActivateOnce();
207 void SuperBlurView::OnBlurViewFinished( Toolkit::GaussianBlurView blurView )
210 Toolkit::SuperBlurView handle( GetOwner() );
211 mBlurFinishedSignal.Emit( handle );
214 void SuperBlurView::ClearBlurResource()
216 if( !mResourcesCleared )
218 DALI_ASSERT_ALWAYS( mGaussianBlurView.size() == mBlurLevels && "must synchronize the GaussianBlurView group if blur levels got changed " );
219 for(unsigned int i=0; i<mBlurLevels;i++)
221 Stage::GetCurrent().Remove( mGaussianBlurView[i] );
222 mGaussianBlurView[i].Deactivate();
223 mGaussianBlurView[i].Reset();
225 mResourcesCleared = true;
229 void SuperBlurView::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
231 unsigned int numChildren = Self().GetChildCount();
233 for( unsigned int i=0; i<numChildren; ++i )
235 Self().GetChildAt(i).SetSize(size);
239 void SuperBlurView::OnControlSizeSet( const Vector3& targetSize )
241 if( mTargetSize != Vector2(targetSize) )
243 mTargetSize = Vector2(targetSize);
245 for(unsigned int i=0; i<mBlurLevels;i++)
247 float exponent = static_cast<float>(i+1);
248 mBlurredImage[i] = FrameBufferImage::New( mTargetSize.width/std::pow(2.f,exponent) , mTargetSize.height/std::pow(2.f,exponent),
249 GAUSSIAN_BLUR_RENDER_TARGET_PIXEL_FORMAT, Dali::Image::Never );
254 } // namespace Internal
256 } // namespace Toolkit