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