Merge "Resolve incorrect position for Ellipsis when mixed LTR & RTL languages and...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-vector-image / animated-vector-image-visual.cpp
1 /*
2  * Copyright (c) 2022 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/devel-api/adaptor-framework/window-devel.h>
23 #include <dali/devel-api/common/stage.h>
24 #include <dali/devel-api/rendering/renderer-devel.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/public-api/rendering/decorated-visual-renderer.h>
27
28 // INTERNAL INCLUDES
29 #include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-signals-devel.h>
30 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
31 #include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
32 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h>
33 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
34 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
35 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
36 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
37 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
38 #include <dali-toolkit/public-api/visuals/visual-properties.h>
39
40 namespace Dali
41 {
42 namespace Toolkit
43 {
44 namespace Internal
45 {
46 namespace
47 {
48 const int CUSTOM_PROPERTY_COUNT(1); // pixel area,
49
50 const Dali::Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
51
52 // stop behavior
53 DALI_ENUM_TO_STRING_TABLE_BEGIN(STOP_BEHAVIOR)
54   DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::DevelImageVisual::StopBehavior, CURRENT_FRAME)
55   DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::DevelImageVisual::StopBehavior, FIRST_FRAME)
56   DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::DevelImageVisual::StopBehavior, LAST_FRAME)
57 DALI_ENUM_TO_STRING_TABLE_END(STOP_BEHAVIOR)
58
59 // looping mode
60 DALI_ENUM_TO_STRING_TABLE_BEGIN(LOOPING_MODE)
61   DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::DevelImageVisual::LoopingMode, RESTART)
62   DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::DevelImageVisual::LoopingMode, AUTO_REVERSE)
63 DALI_ENUM_TO_STRING_TABLE_END(LOOPING_MODE)
64
65 #if defined(DEBUG_ENABLED)
66 Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VECTOR_ANIMATION");
67 #endif
68
69 } // unnamed namespace
70
71 AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties)
72 {
73   AnimatedVectorImageVisualPtr visual(new AnimatedVectorImageVisual(factoryCache, shaderFactory, imageUrl));
74   visual->SetProperties(properties);
75   visual->Initialize();
76   return visual;
77 }
78
79 AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl)
80 {
81   AnimatedVectorImageVisualPtr visual(new AnimatedVectorImageVisual(factoryCache, shaderFactory, imageUrl));
82   visual->Initialize();
83   return visual;
84 }
85
86 AnimatedVectorImageVisual::AnimatedVectorImageVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl)
87 : Visual::Base(factoryCache, Visual::FittingMode::FILL, static_cast<Toolkit::Visual::Type>(Toolkit::DevelVisual::ANIMATED_VECTOR_IMAGE)),
88   mUrl(imageUrl),
89   mAnimationData(),
90   mVectorAnimationTask(new VectorAnimationTask(factoryCache)),
91   mImageVisualShaderFactory(shaderFactory),
92   mVisualSize(),
93   mVisualScale(Vector2::ONE),
94   mPlacementActor(),
95   mPlayState(DevelImageVisual::PlayState::STOPPED),
96   mEventCallback(nullptr),
97   mLoadFailed(false),
98   mRendererAdded(false),
99   mCoreShutdown(false),
100   mRedrawInScalingDown(true)
101 {
102   // the rasterized image is with pre-multiplied alpha format
103   mImpl->mFlags |= Visual::Base::Impl::IS_PREMULTIPLIED_ALPHA;
104
105   if(!mVectorAnimationTask->Load(mUrl.GetUrl()))
106   {
107     mLoadFailed = true;
108   }
109
110   mVectorAnimationTask->UploadCompletedSignal().Connect(this, &AnimatedVectorImageVisual::OnUploadCompleted);
111   mVectorAnimationTask->SetAnimationFinishedCallback(new EventThreadCallback(MakeCallback(this, &AnimatedVectorImageVisual::OnAnimationFinished)));
112
113   auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
114   vectorAnimationManager.AddObserver(*this);
115 }
116
117 AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
118 {
119   if(!mCoreShutdown)
120   {
121     auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
122     vectorAnimationManager.RemoveObserver(*this);
123
124     if(mEventCallback)
125     {
126       mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback(mEventCallback);
127     }
128
129     // Finalize animation task and disconnect the signal in the main thread
130     mVectorAnimationTask->UploadCompletedSignal().Disconnect(this, &AnimatedVectorImageVisual::OnUploadCompleted);
131     mVectorAnimationTask->Finalize();
132   }
133 }
134
135 void AnimatedVectorImageVisual::VectorAnimationManagerDestroyed()
136 {
137   // Core is shutting down. Don't talk to the plugin any more.
138   mCoreShutdown = true;
139 }
140
141 void AnimatedVectorImageVisual::GetNaturalSize(Vector2& naturalSize)
142 {
143   if(mVisualSize != Vector2::ZERO)
144   {
145     naturalSize = mVisualSize;
146   }
147   else
148   {
149     uint32_t width, height;
150     mVectorAnimationTask->GetDefaultSize(width, height);
151     naturalSize.x = width;
152     naturalSize.y = height;
153   }
154
155   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::GetNaturalSize: w = %f, h = %f [%p]\n", naturalSize.width, naturalSize.height, this);
156 }
157
158 void AnimatedVectorImageVisual::DoCreatePropertyMap(Property::Map& map) const
159 {
160   map.Clear();
161   map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::ANIMATED_VECTOR_IMAGE);
162   if(mUrl.IsValid())
163   {
164     map.Insert(Toolkit::ImageVisual::Property::URL, mUrl.GetUrl());
165   }
166   map.Insert(Toolkit::DevelImageVisual::Property::LOOP_COUNT, mAnimationData.loopCount);
167
168   uint32_t startFrame, endFrame;
169   mVectorAnimationTask->GetPlayRange(startFrame, endFrame);
170
171   Property::Array playRange;
172   playRange.PushBack(static_cast<int32_t>(startFrame));
173   playRange.PushBack(static_cast<int32_t>(endFrame));
174   map.Insert(Toolkit::DevelImageVisual::Property::PLAY_RANGE, playRange);
175
176   map.Insert(Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast<int32_t>(mPlayState));
177   map.Insert(Toolkit::DevelImageVisual::Property::CURRENT_FRAME_NUMBER, static_cast<int32_t>(mVectorAnimationTask->GetCurrentFrameNumber()));
178   map.Insert(Toolkit::DevelImageVisual::Property::TOTAL_FRAME_NUMBER, static_cast<int32_t>(mVectorAnimationTask->GetTotalFrameNumber()));
179
180   map.Insert(Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, mAnimationData.stopBehavior);
181   map.Insert(Toolkit::DevelImageVisual::Property::LOOPING_MODE, mAnimationData.loopingMode);
182   map.Insert(Toolkit::DevelImageVisual::Property::REDRAW_IN_SCALING_DOWN, mRedrawInScalingDown);
183
184   Property::Map layerInfo;
185   mVectorAnimationTask->GetLayerInfo(layerInfo);
186   map.Insert(Toolkit::DevelImageVisual::Property::CONTENT_INFO, layerInfo);
187 }
188
189 void AnimatedVectorImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const
190 {
191   // Do nothing
192 }
193
194 void AnimatedVectorImageVisual::EnablePreMultipliedAlpha(bool preMultiplied)
195 {
196   // Make always enable pre multiplied alpha whether preMultiplied value is false.
197   if(!preMultiplied)
198   {
199     DALI_LOG_WARNING("Note : AnimatedVectorVisual cannot disable PreMultipliedAlpha\n");
200   }
201 }
202
203 void AnimatedVectorImageVisual::DoSetProperties(const Property::Map& propertyMap)
204 {
205   // url already passed in from constructor
206   for(Property::Map::SizeType iter = 0; iter < propertyMap.Count(); ++iter)
207   {
208     KeyValuePair keyValue = propertyMap.GetKeyValue(iter);
209     if(keyValue.first.type == Property::Key::INDEX)
210     {
211       DoSetProperty(keyValue.first.indexKey, keyValue.second);
212     }
213     else
214     {
215       if(keyValue.first == LOOP_COUNT_NAME)
216       {
217         DoSetProperty(Toolkit::DevelImageVisual::Property::LOOP_COUNT, keyValue.second);
218       }
219       else if(keyValue.first == PLAY_RANGE_NAME)
220       {
221         DoSetProperty(Toolkit::DevelImageVisual::Property::PLAY_RANGE, keyValue.second);
222       }
223       else if(keyValue.first == STOP_BEHAVIOR_NAME)
224       {
225         DoSetProperty(Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, keyValue.second);
226       }
227       else if(keyValue.first == LOOPING_MODE_NAME)
228       {
229         DoSetProperty(Toolkit::DevelImageVisual::Property::LOOPING_MODE, keyValue.second);
230       }
231       else if(keyValue.first == REDRAW_IN_SCALING_DOWN_NAME)
232       {
233         DoSetProperty(Toolkit::DevelImageVisual::Property::REDRAW_IN_SCALING_DOWN, keyValue.second);
234       }
235     }
236   }
237
238   TriggerVectorRasterization();
239 }
240
241 void AnimatedVectorImageVisual::DoSetProperty(Property::Index index, const Property::Value& value)
242 {
243   switch(index)
244   {
245     case Toolkit::DevelImageVisual::Property::LOOP_COUNT:
246     {
247       int32_t loopCount;
248       if(value.Get(loopCount))
249       {
250         mAnimationData.loopCount = loopCount;
251         mAnimationData.resendFlag |= VectorAnimationTask::RESEND_LOOP_COUNT;
252       }
253       break;
254     }
255     case Toolkit::DevelImageVisual::Property::PLAY_RANGE:
256     {
257       const Property::Array* array = value.GetArray();
258       if(array)
259       {
260         mAnimationData.playRange = *array;
261         mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_RANGE;
262       }
263       break;
264     }
265     case Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR:
266     {
267       int32_t stopBehavior = mAnimationData.stopBehavior;
268       if(Scripting::GetEnumerationProperty(value, STOP_BEHAVIOR_TABLE, STOP_BEHAVIOR_TABLE_COUNT, stopBehavior))
269       {
270         mAnimationData.stopBehavior = DevelImageVisual::StopBehavior::Type(stopBehavior);
271         mAnimationData.resendFlag |= VectorAnimationTask::RESEND_STOP_BEHAVIOR;
272       }
273       break;
274     }
275     case Toolkit::DevelImageVisual::Property::LOOPING_MODE:
276     {
277       int32_t loopingMode = mAnimationData.loopingMode;
278       if(Scripting::GetEnumerationProperty(value, LOOPING_MODE_TABLE, LOOPING_MODE_TABLE_COUNT, loopingMode))
279       {
280         mAnimationData.loopingMode = DevelImageVisual::LoopingMode::Type(loopingMode);
281         mAnimationData.resendFlag |= VectorAnimationTask::RESEND_LOOPING_MODE;
282       }
283       break;
284     }
285     case Toolkit::DevelImageVisual::Property::REDRAW_IN_SCALING_DOWN:
286     {
287       bool redraw;
288       if(value.Get(redraw))
289       {
290         mRedrawInScalingDown = redraw;
291       }
292       break;
293     }
294   }
295 }
296
297 void AnimatedVectorImageVisual::OnInitialize(void)
298 {
299   Shader shader = GenerateShader();
300
301   Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
302
303   mImpl->mRenderer = DecoratedVisualRenderer::New(geometry, shader);
304   mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
305
306   TextureSet textureSet = TextureSet::New();
307   mImpl->mRenderer.SetTextures(textureSet);
308
309   // Register transform properties
310   mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
311 }
312
313 void AnimatedVectorImageVisual::DoSetOnScene(Actor& actor)
314 {
315   // Defer the rasterisation task until we get given a size (by Size Negotiation algorithm)
316
317   // Hold the weak handle of the placement actor and delay the adding of renderer until the rasterization is finished.
318   mPlacementActor = actor;
319
320   if(mLoadFailed)
321   {
322     Vector2 imageSize = Vector2::ZERO;
323     imageSize         = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
324     mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
325     actor.AddRenderer(mImpl->mRenderer);
326     ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
327   }
328   else
329   {
330     mVectorAnimationTask->SetRenderer(mImpl->mRenderer);
331
332     // Add property notification for scaling & size
333     mScaleNotification = actor.AddPropertyNotification(Actor::Property::WORLD_SCALE, StepCondition(0.1f, 1.0f));
334     mScaleNotification.NotifySignal().Connect(this, &AnimatedVectorImageVisual::OnScaleNotification);
335
336     mSizeNotification = actor.AddPropertyNotification(Actor::Property::SIZE, StepCondition(3.0f));
337     mSizeNotification.NotifySignal().Connect(this, &AnimatedVectorImageVisual::OnSizeNotification);
338
339     DevelActor::VisibilityChangedSignal(actor).Connect(this, &AnimatedVectorImageVisual::OnControlVisibilityChanged);
340
341     Window window = DevelWindow::Get(actor);
342     if(window)
343     {
344       DevelWindow::VisibilityChangedSignal(window).Connect(this, &AnimatedVectorImageVisual::OnWindowVisibilityChanged);
345     }
346   }
347
348   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::DoSetOnScene [%p]\n", this);
349 }
350
351 void AnimatedVectorImageVisual::DoSetOffScene(Actor& actor)
352 {
353   StopAnimation();
354   SendAnimationData();
355
356   if(mImpl->mRenderer)
357   {
358     actor.RemoveRenderer(mImpl->mRenderer);
359     mRendererAdded = false;
360   }
361
362   // Remove property notification
363   actor.RemovePropertyNotification(mScaleNotification);
364   actor.RemovePropertyNotification(mSizeNotification);
365
366   DevelActor::VisibilityChangedSignal(actor).Disconnect(this, &AnimatedVectorImageVisual::OnControlVisibilityChanged);
367
368   Window window = DevelWindow::Get(actor);
369   if(window)
370   {
371     DevelWindow::VisibilityChangedSignal(window).Disconnect(this, &AnimatedVectorImageVisual::OnWindowVisibilityChanged);
372   }
373
374   mPlacementActor.Reset();
375
376   // Reset the visual size to zero so that when adding the actor back to stage the rasterization is forced
377   mVisualSize  = Vector2::ZERO;
378   mVisualScale = Vector2::ONE;
379
380   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::DoSetOffScene [%p]\n", this);
381 }
382
383 void AnimatedVectorImageVisual::OnSetTransform()
384 {
385   Vector2 visualSize = mImpl->mTransform.GetVisualSize(mImpl->mControlSize);
386
387   if(IsOnScene() && visualSize != mVisualSize)
388   {
389     DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnSetTransform: width = %f, height = %f [%p]\n", visualSize.width, visualSize.height, this);
390
391     mVisualSize = visualSize;
392
393     SetVectorImageSize();
394
395     if(mPlayState == DevelImageVisual::PlayState::PLAYING && mAnimationData.playState != DevelImageVisual::PlayState::PLAYING)
396     {
397       mAnimationData.playState = DevelImageVisual::PlayState::PLAYING;
398       mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE;
399     }
400
401     SendAnimationData();
402   }
403 }
404
405 void AnimatedVectorImageVisual::UpdateShader()
406 {
407   if(mImpl->mRenderer)
408   {
409     Shader shader = GenerateShader();
410     mImpl->mRenderer.SetShader(shader);
411   }
412 }
413
414 void AnimatedVectorImageVisual::OnDoAction(const Property::Index actionId, const Property::Value& attributes)
415 {
416   // Check if action is valid for this visual type and perform action if possible
417   switch(actionId)
418   {
419     case DevelAnimatedVectorImageVisual::Action::PLAY:
420     {
421       if(IsOnScene() && mVisualSize != Vector2::ZERO)
422       {
423         if(mAnimationData.playState != DevelImageVisual::PlayState::PLAYING)
424         {
425           mAnimationData.playState = DevelImageVisual::PlayState::PLAYING;
426           mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE;
427         }
428       }
429       mPlayState = DevelImageVisual::PlayState::PLAYING;
430       break;
431     }
432     case DevelAnimatedVectorImageVisual::Action::PAUSE:
433     {
434       if(mAnimationData.playState == DevelImageVisual::PlayState::PLAYING)
435       {
436         mAnimationData.playState = DevelImageVisual::PlayState::PAUSED;
437         mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE;
438       }
439       mPlayState = DevelImageVisual::PlayState::PAUSED;
440       break;
441     }
442     case DevelAnimatedVectorImageVisual::Action::STOP:
443     {
444       if(mAnimationData.playState != DevelImageVisual::PlayState::STOPPED)
445       {
446         mAnimationData.playState = DevelImageVisual::PlayState::STOPPED;
447         mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE;
448       }
449       mPlayState = DevelImageVisual::PlayState::STOPPED;
450       break;
451     }
452     case DevelAnimatedVectorImageVisual::Action::JUMP_TO:
453     {
454       int32_t frameNumber;
455       if(attributes.Get(frameNumber))
456       {
457         mAnimationData.currentFrame = frameNumber;
458         mAnimationData.resendFlag |= VectorAnimationTask::RESEND_CURRENT_FRAME;
459       }
460       break;
461     }
462   }
463
464   TriggerVectorRasterization();
465 }
466
467 void AnimatedVectorImageVisual::OnUploadCompleted()
468 {
469   // If weak handle is holding a placement actor, it is the time to add the renderer to actor.
470   Actor actor = mPlacementActor.GetHandle();
471   if(actor && !mRendererAdded)
472   {
473     actor.AddRenderer(mImpl->mRenderer);
474     mRendererAdded = true;
475
476     ResourceReady(Toolkit::Visual::ResourceStatus::READY);
477
478     DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnUploadCompleted: Renderer is added [%p]\n", this);
479   }
480 }
481
482 void AnimatedVectorImageVisual::OnAnimationFinished()
483 {
484   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnAnimationFinished: action state = %d [%p]\n", mPlayState, this);
485
486   if(mPlayState != DevelImageVisual::PlayState::STOPPED)
487   {
488     mPlayState = DevelImageVisual::PlayState::STOPPED;
489
490     mAnimationData.playState = DevelImageVisual::PlayState::STOPPED;
491
492     if(mImpl->mEventObserver)
493     {
494       mImpl->mEventObserver->NotifyVisualEvent(*this, DevelAnimatedVectorImageVisual::Signal::ANIMATION_FINISHED);
495     }
496   }
497
498   if(mImpl->mRenderer)
499   {
500     mImpl->mRenderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED);
501   }
502 }
503
504 void AnimatedVectorImageVisual::SendAnimationData()
505 {
506   if(mAnimationData.resendFlag)
507   {
508     mVectorAnimationTask->SetAnimationData(mAnimationData);
509
510     if(mImpl->mRenderer)
511     {
512       if(mAnimationData.playState == DevelImageVisual::PlayState::PLAYING)
513       {
514         mImpl->mRenderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY);
515       }
516       else
517       {
518         mImpl->mRenderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED);
519       }
520     }
521
522     mAnimationData.resendFlag = 0;
523   }
524 }
525
526 void AnimatedVectorImageVisual::SetVectorImageSize()
527 {
528   uint32_t width  = static_cast<uint32_t>(mVisualSize.width * mVisualScale.width);
529   uint32_t height = static_cast<uint32_t>(mVisualSize.height * mVisualScale.height);
530
531   mAnimationData.width  = width;
532   mAnimationData.height = height;
533   mAnimationData.resendFlag |= VectorAnimationTask::RESEND_SIZE;
534 }
535
536 void AnimatedVectorImageVisual::StopAnimation()
537 {
538   if(mAnimationData.playState != DevelImageVisual::PlayState::STOPPED)
539   {
540     mAnimationData.playState = DevelImageVisual::PlayState::STOPPED;
541     mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE;
542
543     mPlayState = DevelImageVisual::PlayState::STOPPED;
544   }
545 }
546
547 void AnimatedVectorImageVisual::TriggerVectorRasterization()
548 {
549   if(!mEventCallback && !mCoreShutdown)
550   {
551     mEventCallback               = MakeCallback(this, &AnimatedVectorImageVisual::OnProcessEvents);
552     auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
553     vectorAnimationManager.RegisterEventCallback(mEventCallback);
554     Stage::GetCurrent().KeepRendering(0.0f); // Trigger event processing
555   }
556 }
557
558 void AnimatedVectorImageVisual::OnScaleNotification(PropertyNotification& source)
559 {
560   Actor actor = mPlacementActor.GetHandle();
561   if(actor)
562   {
563     Vector3 scale = actor.GetProperty<Vector3>(Actor::Property::WORLD_SCALE);
564
565     if(mRedrawInScalingDown || scale.width >= 1.0f || scale.height >= 1.0f)
566     {
567       mVisualScale.width  = scale.width;
568       mVisualScale.height = scale.height;
569
570       DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnScaleNotification: scale = %f, %f [%p]\n", mVisualScale.width, mVisualScale.height, this);
571
572       SetVectorImageSize();
573       SendAnimationData();
574
575       Stage::GetCurrent().KeepRendering(0.0f); // Trigger event processing
576     }
577   }
578 }
579
580 void AnimatedVectorImageVisual::OnSizeNotification(PropertyNotification& source)
581 {
582   Actor actor = mPlacementActor.GetHandle();
583   if(actor)
584   {
585     Vector3 size       = actor.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
586     mVisualSize.width  = size.width;
587     mVisualSize.height = size.height;
588
589     DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnSizeNotification: size = %f, %f [%p]\n", mVisualSize.width, mVisualSize.height, this);
590
591     SetVectorImageSize();
592     SendAnimationData();
593
594     Stage::GetCurrent().KeepRendering(0.0f); // Trigger event processing
595   }
596 }
597
598 void AnimatedVectorImageVisual::OnControlVisibilityChanged(Actor actor, bool visible, DevelActor::VisibilityChange::Type type)
599 {
600   if(!visible)
601   {
602     StopAnimation();
603     TriggerVectorRasterization();
604
605     DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnControlVisibilityChanged: invisibile. Pause animation [%p]\n", this);
606   }
607 }
608
609 void AnimatedVectorImageVisual::OnWindowVisibilityChanged(Window window, bool visible)
610 {
611   if(!visible)
612   {
613     StopAnimation();
614     TriggerVectorRasterization();
615
616     DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnWindowVisibilityChanged: invisibile. Pause animation [%p]\n", this);
617   }
618 }
619
620 void AnimatedVectorImageVisual::OnProcessEvents()
621 {
622   SendAnimationData();
623
624   mEventCallback = nullptr; // The callback will be deleted in the VectorAnimationManager
625 }
626
627 Shader AnimatedVectorImageVisual::GenerateShader() const
628 {
629   Shader shader;
630   if(mImpl->mCustomShader)
631   {
632     shader = Shader::New(mImpl->mCustomShader->mVertexShader.empty() ? mImageVisualShaderFactory.GetVertexShaderSource().data() : mImpl->mCustomShader->mVertexShader,
633                          mImpl->mCustomShader->mFragmentShader.empty() ? mImageVisualShaderFactory.GetFragmentShaderSource().data() : mImpl->mCustomShader->mFragmentShader,
634                          mImpl->mCustomShader->mHints);
635
636     shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
637   }
638   else
639   {
640     shader = mImageVisualShaderFactory.GetShader(
641       mFactoryCache,
642       ImageVisualShaderFeature::FeatureBuilder()
643         .EnableRoundedCorner(IsRoundedCornerRequired())
644         .EnableBorderline(IsBorderlineRequired()));
645   }
646   return shader;
647 }
648
649 } // namespace Internal
650
651 } // namespace Toolkit
652
653 } // namespace Dali