(Vector) Fix invalid callback issue
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-vector-image / vector-animation-task.cpp
index 4d31135..b1e9bea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -46,14 +46,14 @@ Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging,
 } // unnamed namespace
 
 VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache)
-: mUrl(),
+: AsyncTask(MakeCallback(this, &VectorAnimationTask::TaskCompleted), AsyncTask::PriorityType::HIGH, AsyncTask::ThreadType::WORKER_THREAD),
+  mUrl(),
   mVectorRenderer(VectorAnimationRenderer::New()),
   mAnimationData(),
   mVectorAnimationThread(factoryCache.GetVectorAnimationManager().GetVectorAnimationThread()),
   mConditionalWait(),
   mResourceReadySignal(),
-  mAnimationFinishedTrigger(),
-  mLoadCompletedTrigger(new EventThreadCallback(MakeCallback(this, &VectorAnimationTask::OnLoadCompleted))),
+  mLoadCompletedCallback(MakeCallback(this, &VectorAnimationTask::OnLoadCompleted)),
   mPlayState(PlayState::STOPPED),
   mStopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME),
   mLoopingMode(DevelImageVisual::LoopingMode::RESTART),
@@ -76,7 +76,9 @@ VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache)
   mAnimationDataUpdated(false),
   mDestroyTask(false),
   mLoadRequest(false),
-  mLoadFailed(false)
+  mLoadFailed(false),
+  mRasterized(false),
+  mKeepAnimation(false)
 {
   mVectorRenderer.UploadCompletedSignal().Connect(this, &VectorAnimationTask::OnUploadCompleted);
 }
@@ -86,14 +88,30 @@ VectorAnimationTask::~VectorAnimationTask()
   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::~VectorAnimationTask: destructor [%p]\n", this);
 }
 
+void VectorAnimationTask::Process()
+{
+  mRasterized = Rasterize();
+}
+
+bool VectorAnimationTask::IsReady()
+{
+  return true;
+}
+
 void VectorAnimationTask::Finalize()
 {
   ConditionalWait::ScopedLock lock(mConditionalWait);
 
   // Release some objects in the main thread
-  if(mAnimationFinishedTrigger)
+  if(mAnimationFinishedCallback)
+  {
+    mVectorAnimationThread.RemoveEventTriggerCallback(mAnimationFinishedCallback.get());
+    mAnimationFinishedCallback.reset();
+  }
+  if(mLoadCompletedCallback)
   {
-    mAnimationFinishedTrigger.reset();
+    mVectorAnimationThread.RemoveEventTriggerCallback(mLoadCompletedCallback.get());
+    mLoadCompletedCallback.reset();
   }
 
   mVectorRenderer.Finalize();
@@ -101,14 +119,32 @@ void VectorAnimationTask::Finalize()
   mDestroyTask = true;
 }
 
-bool VectorAnimationTask::Load()
+void VectorAnimationTask::TaskCompleted(VectorAnimationTaskPtr task)
+{
+  mVectorAnimationThread.OnTaskCompleted(task, task->IsRasterized(), task->IsAnimating());
+}
+
+bool VectorAnimationTask::IsRasterized()
+{
+  return mRasterized;
+}
+
+bool VectorAnimationTask::IsAnimating()
+{
+  return mKeepAnimation;
+}
+
+bool VectorAnimationTask::Load(bool synchronousLoading)
 {
   if(!mVectorRenderer.Load(mUrl))
   {
     DALI_LOG_ERROR("VectorAnimationTask::Load: Load failed [%s]\n", mUrl.c_str());
     mLoadRequest = false;
     mLoadFailed  = true;
-    mLoadCompletedTrigger->Trigger();
+    if(!synchronousLoading && mLoadCompletedCallback)
+    {
+      mVectorAnimationThread.AddEventTriggerCallback(mLoadCompletedCallback.get());
+    }
     return false;
   }
 
@@ -120,7 +156,10 @@ bool VectorAnimationTask::Load()
   mFrameDurationMicroSeconds = MICROSECONDS_PER_SECOND / mFrameRate;
 
   mLoadRequest = false;
-  mLoadCompletedTrigger->Trigger();
+  if(!synchronousLoading && mLoadCompletedCallback)
+  {
+    mVectorAnimationThread.AddEventTriggerCallback(mLoadCompletedCallback.get());
+  }
 
   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Load: file = %s [%d frames, %f fps] [%p]\n", mUrl.c_str(), mTotalFrame, mFrameRate, this);
 
@@ -136,12 +175,27 @@ void VectorAnimationTask::SetRenderer(Renderer renderer)
   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetRenderer [%p]\n", this);
 }
 
-void VectorAnimationTask::RequestLoad(const std::string& url)
+void VectorAnimationTask::RequestLoad(const std::string& url, bool synchronousLoading)
 {
-  mUrl         = url;
-  mLoadRequest = true;
+  mUrl = url;
 
-  mVectorAnimationThread.AddTask(this);
+  if(!synchronousLoading)
+  {
+    mLoadRequest = true;
+
+    mVectorAnimationThread.AddTask(this);
+  }
+  else
+  {
+    Load(true);
+
+    OnLoadCompleted();
+  }
+}
+
+bool VectorAnimationTask::IsLoadRequested() const
+{
+  return mLoadRequest;
 }
 
 void VectorAnimationTask::SetAnimationData(const AnimationData& data)
@@ -210,13 +264,10 @@ void VectorAnimationTask::PauseAnimation()
   }
 }
 
-void VectorAnimationTask::SetAnimationFinishedCallback(EventThreadCallback* callback)
+void VectorAnimationTask::SetAnimationFinishedCallback(CallbackBase* callback)
 {
   ConditionalWait::ScopedLock lock(mConditionalWait);
-  if(callback)
-  {
-    mAnimationFinishedTrigger = std::unique_ptr<EventThreadCallback>(callback);
-  }
+  mAnimationFinishedCallback = std::unique_ptr<CallbackBase>(callback);
 }
 
 void VectorAnimationTask::SetLoopCount(int32_t count)
@@ -280,38 +331,33 @@ void VectorAnimationTask::SetPlayRange(const Property::Array& playRange)
   }
 
   // Make sure the range specified is between 0 and the total frame number
-  if(startFrame < mTotalFrame && endFrame < mTotalFrame)
+  startFrame = std::min(startFrame, mTotalFrame - 1);
+  endFrame   = std::min(endFrame, mTotalFrame - 1);
+
+  // If the range is not in order swap values
+  if(startFrame > endFrame)
   {
-    // If the range is not in order swap values
-    if(startFrame > endFrame)
+    uint32_t temp = startFrame;
+    startFrame    = endFrame;
+    endFrame      = temp;
+  }
+
+  if(startFrame != mStartFrame || endFrame != mEndFrame)
+  {
+    mStartFrame = startFrame;
+    mEndFrame   = endFrame;
+
+    // If the current frame is out of the range, change the current frame also.
+    if(mStartFrame > mCurrentFrame)
     {
-      uint32_t temp = startFrame;
-      startFrame    = endFrame;
-      endFrame      = temp;
+      mCurrentFrame = mStartFrame;
     }
-
-    if(startFrame != mStartFrame || endFrame != mEndFrame)
+    else if(mEndFrame < mCurrentFrame)
     {
-      mStartFrame = startFrame;
-      mEndFrame   = endFrame;
-
-      // If the current frame is out of the range, change the current frame also.
-      if(mStartFrame > mCurrentFrame)
-      {
-        mCurrentFrame = mStartFrame;
-      }
-      else if(mEndFrame < mCurrentFrame)
-      {
-        mCurrentFrame = mEndFrame;
-      }
-
-      DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetPlayRange: [%d, %d] [%s] [%p]\n", mStartFrame, mEndFrame, mUrl.c_str(), this);
+      mCurrentFrame = mEndFrame;
     }
-  }
-  else
-  {
-    DALI_LOG_ERROR("VectorAnimationTask::SetPlayRange: Invalid range (%d, %d) [%s] [%p]\n", startFrame, endFrame, mUrl.c_str(), this);
-    return;
+
+    DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetPlayRange: [%d, %d] [%s] [%p]\n", mStartFrame, mEndFrame, mUrl.c_str(), this);
   }
 }
 
@@ -381,11 +427,11 @@ VectorAnimationTask::ResourceReadySignalType& VectorAnimationTask::ResourceReady
   return mResourceReadySignal;
 }
 
-bool VectorAnimationTask::Rasterize(bool& keepAnimation)
+bool VectorAnimationTask::Rasterize()
 {
   bool     stopped = false;
   uint32_t currentFrame;
-  keepAnimation = false;
+  mKeepAnimation = false;
 
   {
     ConditionalWait::ScopedLock lock(mConditionalWait);
@@ -394,15 +440,11 @@ bool VectorAnimationTask::Rasterize(bool& keepAnimation)
       // The task will be destroyed. We don't need rasterization.
       return false;
     }
+  }
 
-    if(mLoadRequest)
-    {
-      bool result = Load();
-      if(!result)
-      {
-        return false;
-      }
-    }
+  if(mLoadRequest)
+  {
+    return Load(false);
   }
 
   if(mLoadFailed)
@@ -494,12 +536,18 @@ bool VectorAnimationTask::Rasterize(bool& keepAnimation)
     mForward     = true;
     mCurrentLoop = 0;
 
+    if(mVectorRenderer)
+    {
+      // Notify the Renderer that rendering is stopped.
+      mVectorRenderer.RenderStopped();
+    }
+
     // Animation is finished
     {
       ConditionalWait::ScopedLock lock(mConditionalWait);
-      if(mNeedAnimationFinishedTrigger && mAnimationFinishedTrigger)
+      if(mNeedAnimationFinishedTrigger && mAnimationFinishedCallback)
       {
-        mAnimationFinishedTrigger->Trigger();
+        mVectorAnimationThread.AddEventTriggerCallback(mAnimationFinishedCallback.get());
       }
     }
 
@@ -508,7 +556,7 @@ bool VectorAnimationTask::Rasterize(bool& keepAnimation)
 
   if(mPlayState != PlayState::PAUSED && mPlayState != PlayState::STOPPED)
   {
-    keepAnimation = true;
+    mKeepAnimation = true;
   }
 
   return true;
@@ -631,6 +679,14 @@ void VectorAnimationTask::ApplyAnimationData()
     mVectorRenderer.InvalidateBuffer();
   }
 
+  if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_DYNAMIC_PROPERTY)
+  {
+    for(auto&& iter : mAnimationData[index].dynamicProperties)
+    {
+      mVectorRenderer.AddPropertyValueCallback(iter.keyPath, static_cast<VectorAnimationRenderer::VectorProperty>(iter.property), iter.callback, iter.id);
+    }
+  }
+
   if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_PLAY_STATE)
   {
     if(mAnimationData[index].playState == DevelImageVisual::PlayState::PLAYING)
@@ -647,32 +703,25 @@ void VectorAnimationTask::ApplyAnimationData()
     }
   }
 
+  // reset data
+  mAnimationData[index].dynamicProperties.clear();
   mAnimationData[index].resendFlag = 0;
 }
 
 void VectorAnimationTask::OnUploadCompleted()
 {
-  mResourceReadySignal.Emit(true);
+  mResourceReadySignal.Emit(ResourceStatus::READY);
 }
 
 void VectorAnimationTask::OnLoadCompleted()
 {
   if(!mLoadFailed)
   {
-    if(mWidth == 0 && mHeight == 0)
-    {
-      uint32_t width, height;
-      mVectorRenderer.GetDefaultSize(width, height);
-
-      SetSize(width, height);
-
-      mVectorAnimationThread.AddTask(this);
-    }
+    mResourceReadySignal.Emit(ResourceStatus::LOADED);
   }
   else
   {
-    // Load failed
-    mResourceReadySignal.Emit(false);
+    mResourceReadySignal.Emit(ResourceStatus::FAILED);
   }
 }
 } // namespace Internal