Fixed some errors reported by Clang
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-vector-image / animated-vector-image-visual.cpp
1 /*
2  * Copyright (c) 2018 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-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/common/stage-devel.h>
24 #include <dali/integration-api/debug.h>
25
26 // INTERNAL INCLUDES
27 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
28 #include <dali-toolkit/public-api/visuals/visual-properties.h>
29 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
30 #include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-signals-devel.h>
31 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
32 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
33 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
34 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
35 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h>
36
37 namespace Dali
38 {
39
40 namespace Toolkit
41 {
42
43 namespace Internal
44 {
45
46 namespace
47 {
48
49 const Dali::Vector4 FULL_TEXTURE_RECT( 0.f, 0.f, 1.f, 1.f );
50 constexpr auto LOOP_FOREVER = -1;
51
52 } // unnamed namespace
53
54 AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties )
55 {
56   AnimatedVectorImageVisualPtr visual( new AnimatedVectorImageVisual( factoryCache, shaderFactory, imageUrl ) );
57   visual->SetProperties( properties );
58
59   return visual;
60 }
61
62 AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl )
63 {
64   AnimatedVectorImageVisualPtr visual( new AnimatedVectorImageVisual( factoryCache, shaderFactory, imageUrl ) );
65
66   return visual;
67 }
68
69 AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl )
70 : Visual::Base( factoryCache, Visual::FittingMode::FILL ),
71   mImageVisualShaderFactory( shaderFactory ),
72   mUrl( imageUrl ),
73   mVisualSize(),
74   mPlayRange( 0.0f, 1.0f ),
75   mPlacementActor(),
76   mVectorRasterizeThread(),
77   mLoopCount( LOOP_FOREVER ),
78   mActionStatus( DevelAnimatedVectorImageVisual::Action::STOP )
79 {
80   // the rasterized image is with pre-multiplied alpha format
81   mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
82 }
83
84 AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
85 {
86 }
87
88 void AnimatedVectorImageVisual::GetNaturalSize( Vector2& naturalSize )
89 {
90   naturalSize = mVisualSize;
91 }
92
93 void AnimatedVectorImageVisual::DoCreatePropertyMap( Property::Map& map ) const
94 {
95   map.Clear();
96   map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::ANIMATED_VECTOR_IMAGE );
97   if( mUrl.IsValid() )
98   {
99     map.Insert( Toolkit::ImageVisual::Property::URL, mUrl.GetUrl() );
100   }
101   map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast< int >( mLoopCount ) );
102   map.Insert( Toolkit::DevelImageVisual::Property::PLAY_RANGE, static_cast< Vector2 >( mPlayRange ) );
103
104   if( mVectorRasterizeThread )
105   {
106     map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int >( mVectorRasterizeThread->GetPlayState() ) );
107   }
108   else
109   {
110     map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int >( DevelImageVisual::PlayState::STOPPED ) );
111   }
112 }
113
114 void AnimatedVectorImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
115 {
116   // Do nothing
117 }
118
119 void AnimatedVectorImageVisual::DoSetProperties( const Property::Map& propertyMap )
120 {
121   // url already passed in from constructor
122   for( Property::Map::SizeType iter = 0; iter < propertyMap.Count(); ++iter )
123   {
124     KeyValuePair keyValue = propertyMap.GetKeyValue( iter );
125     if( keyValue.first.type == Property::Key::INDEX )
126     {
127       DoSetProperty( keyValue.first.indexKey, keyValue.second );
128     }
129     else
130     {
131        if( keyValue.first == LOOP_COUNT_NAME )
132        {
133           DoSetProperty( Toolkit::DevelImageVisual::Property::LOOP_COUNT, keyValue.second );
134        }
135        else if( keyValue.first == PLAY_RANGE_NAME )
136        {
137           DoSetProperty( Toolkit::DevelImageVisual::Property::PLAY_RANGE, keyValue.second );
138        }
139     }
140   }
141 }
142
143 void AnimatedVectorImageVisual::DoSetProperty( Property::Index index, const Property::Value& value )
144 {
145   switch(index)
146   {
147     case Toolkit::DevelImageVisual::Property::LOOP_COUNT:
148     {
149       int32_t loopCount;
150       if( value.Get( loopCount ) )
151       {
152         mLoopCount = loopCount;
153         if( mVectorRasterizeThread )
154         {
155           mVectorRasterizeThread->SetLoopCount( loopCount );
156         }
157       }
158       break;
159     }
160     case Toolkit::DevelImageVisual::Property::PLAY_RANGE:
161     {
162       Vector2 range;
163       if( value.Get( range ) )
164       {
165         // Make sure the range specified is between 0.0 and 1.0
166         if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
167         {
168           Vector2 orderedRange( range );
169           // If the range is not in order swap values
170           if( range.x > range.y )
171           {
172             orderedRange = Vector2( range.y, range.x );
173           }
174
175           mPlayRange = orderedRange;
176
177           if( mVectorRasterizeThread )
178           {
179             mVectorRasterizeThread->SetPlayRange( mPlayRange );
180           }
181         }
182       }
183       break;
184     }
185   }
186 }
187
188 void AnimatedVectorImageVisual::DoSetOnStage( Actor& actor )
189 {
190   Shader shader;
191
192   if( mImpl->mCustomShader )
193   {
194     shader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? mImageVisualShaderFactory.GetVertexShaderSource() : mImpl->mCustomShader->mVertexShader,
195                           mImpl->mCustomShader->mFragmentShader.empty() ? mImageVisualShaderFactory.GetFragmentShaderSource() : mImpl->mCustomShader->mFragmentShader,
196                           mImpl->mCustomShader->mHints );
197
198     shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
199   }
200   else
201   {
202     shader = mImageVisualShaderFactory.GetShader( mFactoryCache, false, true );
203   }
204
205   Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
206
207   mImpl->mRenderer = Renderer::New( geometry, shader );
208
209   TextureSet textureSet = TextureSet::New();
210   mImpl->mRenderer.SetTextures( textureSet );
211
212   // Register transform properties
213   mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
214
215   // Defer the rasterisation task until we get given a size (by Size Negotiation algorithm)
216
217   // Hold the weak handle of the placement actor and delay the adding of renderer until the rasterization is finished.
218   mPlacementActor = actor;
219
220   // This visual needs it's size set before it can be rasterized hence set ResourceReady once on stage
221   ResourceReady( Toolkit::Visual::ResourceStatus::READY );
222 }
223
224 void AnimatedVectorImageVisual::DoSetOffStage( Actor& actor )
225 {
226   if( mVectorRasterizeThread )
227   {
228     mVectorRasterizeThread->PauseAnimation();
229     DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
230     mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE;
231   }
232
233   if( mImpl->mRenderer )
234   {
235     actor.RemoveRenderer( mImpl->mRenderer );
236     mImpl->mRenderer.Reset();
237   }
238
239   mPlacementActor.Reset();
240
241   // Reset the visual size to zero so that when adding the actor back to stage the rasterization is forced
242   mVisualSize = Vector2::ZERO;
243 }
244
245 void AnimatedVectorImageVisual::OnSetTransform()
246 {
247   Vector2 visualSize = mImpl->mTransform.GetVisualSize( mImpl->mControlSize );
248
249   if( IsOnStage() )
250   {
251     if( visualSize != mVisualSize )
252     {
253       mVisualSize = visualSize;
254
255       if( !mVectorRasterizeThread )
256       {
257         uint32_t width = static_cast< uint32_t >( visualSize.width );
258         uint32_t height = static_cast< uint32_t >( visualSize.height );
259
260         mVectorRasterizeThread = std::unique_ptr< VectorRasterizeThread >( new VectorRasterizeThread( mUrl.GetUrl(), mImpl->mRenderer, width, height ) );
261
262         mVectorRasterizeThread->SetResourceReadyCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnResourceReady ) ) );
263         mVectorRasterizeThread->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) );
264         mVectorRasterizeThread->SetLoopCount( mLoopCount );
265         mVectorRasterizeThread->SetPlayRange( mPlayRange );
266
267         mVectorRasterizeThread->Start();
268
269         if( mActionStatus == DevelAnimatedVectorImageVisual::Action::PLAY )
270         {
271           mVectorRasterizeThread->StartAnimation();
272           DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::CONTINUOUSLY );
273         }
274         else
275         {
276           // Render one frame
277           mVectorRasterizeThread->RenderFrame();
278         }
279       }
280       else
281       {
282         uint32_t width = static_cast< uint32_t >( visualSize.width );
283         uint32_t height = static_cast< uint32_t >( visualSize.height );
284
285         mVectorRasterizeThread->SetSize( width, height );
286       }
287     }
288   }
289 }
290
291 void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, const Property::Value& attributes )
292 {
293   // Check if action is valid for this visual type and perform action if possible
294   switch( actionId )
295   {
296     case DevelAnimatedVectorImageVisual::Action::PLAY:
297     {
298       if( IsOnStage())
299       {
300         if( mVectorRasterizeThread )
301         {
302           mVectorRasterizeThread->StartAnimation();
303           DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::CONTINUOUSLY );   //TODO: Should manage this globally
304         }
305       }
306       mActionStatus = DevelAnimatedVectorImageVisual::Action::PLAY;
307       break;
308     }
309     case DevelAnimatedVectorImageVisual::Action::PAUSE:
310     {
311       if( mVectorRasterizeThread )
312       {
313         mVectorRasterizeThread->PauseAnimation();
314         DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
315       }
316       mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE;
317       break;
318     }
319     case DevelAnimatedVectorImageVisual::Action::STOP:
320     {
321       if( mVectorRasterizeThread )
322       {
323         bool emitSignal = false;
324         if( mVectorRasterizeThread->GetPlayState() != DevelImageVisual::PlayState::STOPPED )
325         {
326           emitSignal = true;
327         }
328
329         mVectorRasterizeThread->StopAnimation();
330         DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
331
332         if( emitSignal )
333         {
334           OnAnimationFinished();
335         }
336       }
337       mActionStatus = DevelAnimatedVectorImageVisual::Action::STOP;
338       break;
339     }
340   }
341 }
342
343 void AnimatedVectorImageVisual::OnResourceReady()
344 {
345   // If weak handle is holding a placement actor, it is the time to add the renderer to actor.
346   Actor actor = mPlacementActor.GetHandle();
347   if( actor )
348   {
349     actor.AddRenderer( mImpl->mRenderer );
350     // reset the weak handle so that the renderer only get added to actor once
351     mPlacementActor.Reset();
352
353     Stage::GetCurrent().KeepRendering( 0.0f );
354   }
355 }
356
357 void AnimatedVectorImageVisual::OnAnimationFinished()
358 {
359   if( mImpl->mEventObserver )
360   {
361     mImpl->mEventObserver->NotifyVisualEvent( *this, DevelAnimatedVectorImageVisual::Signal::ANIMATION_FINISHED );
362   }
363 }
364
365 } // namespace Internal
366
367 } // namespace Toolkit
368
369 } // namespace Dali