(Vector) Fix crash issues
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-vector-image / vector-animation-task.cpp
index 8258fb7..e0c08bd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
@@ -20,6 +20,8 @@
 
 // EXTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
+#include <dali/public-api/object/property-array.h>
+#include <dali/public-api/math/math-utils.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
@@ -94,6 +96,8 @@ VectorAnimationTask::~VectorAnimationTask()
 
 void VectorAnimationTask::Finalize()
 {
+  ConditionalWait::ScopedLock lock( mConditionalWait );
+
   // Release some objects in the main thread
   if( mAnimationFinishedTrigger )
   {
@@ -201,10 +205,60 @@ void VectorAnimationTask::SetLoopCount( int32_t count )
   }
 }
 
-void VectorAnimationTask::SetPlayRange( uint32_t startFrame, uint32_t endFrame )
+void VectorAnimationTask::SetPlayRange( Property::Array& playRange )
 {
+  ConditionalWait::ScopedLock lock( mConditionalWait );
+
+  bool valid = false;
+  uint32_t startFrame = 0, endFrame = 0;
+  size_t count = playRange.Count();
+
+  if( count >= 2 )
+  {
+    int32_t start = 0, end = 0;
+    if( playRange.GetElementAt( 0 ).Get( start ) && playRange.GetElementAt( 1 ).Get( end ) )
+    {
+      startFrame = static_cast< uint32_t >( start );
+      endFrame = static_cast< uint32_t >( end );
+      valid = true;
+    }
+    else
+    {
+      std::string startMarker, endMarker;
+      if( playRange.GetElementAt( 0 ).Get( startMarker ) && playRange.GetElementAt( 1 ).Get( endMarker ) )
+      {
+        if( mVectorRenderer )
+        {
+          uint32_t frame;   // We don't use this later
+          if( mVectorRenderer.GetMarkerInfo( startMarker, startFrame, frame ) && mVectorRenderer.GetMarkerInfo( endMarker, frame, endFrame ) )
+          {
+            valid = true;
+          }
+        }
+      }
+    }
+  }
+  else if( count == 1 )
+  {
+    std::string marker;
+    if( playRange.GetElementAt( 0 ).Get( marker ) )
+    {
+      if( mVectorRenderer )
+      {
+        mVectorRenderer.GetMarkerInfo( marker, startFrame, endFrame );
+        valid = true;
+      }
+    }
+  }
+
+  if( !valid )
+  {
+    DALI_LOG_ERROR( "VectorAnimationTask::SetPlayRange: Invalid range [%p]\n", this );
+    return;
+  }
+
   // Make sure the range specified is between 0 and the total frame number
-  if( ( startFrame < mTotalFrame ) && ( endFrame < mTotalFrame ) )
+  if( startFrame < mTotalFrame && endFrame < mTotalFrame )
   {
     // If the range is not in order swap values
     if( startFrame > endFrame )
@@ -216,8 +270,6 @@ void VectorAnimationTask::SetPlayRange( uint32_t startFrame, uint32_t endFrame )
 
     if( startFrame != mStartFrame || endFrame != mEndFrame )
     {
-      ConditionalWait::ScopedLock lock( mConditionalWait );
-
       mStartFrame = startFrame;
       mEndFrame = endFrame;
 
@@ -240,6 +292,11 @@ void VectorAnimationTask::SetPlayRange( uint32_t startFrame, uint32_t endFrame )
       DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetPlayRange: [%d, %d] [%p]\n", mStartFrame, mEndFrame, this );
     }
   }
+  else
+  {
+    DALI_LOG_ERROR( "VectorAnimationTask::SetPlayRange: Invalid range (%d, %d) [%p]\n", startFrame, endFrame, this );
+    return;
+  }
 }
 
 void VectorAnimationTask::GetPlayRange( uint32_t& startFrame, uint32_t& endFrame )
@@ -363,7 +420,7 @@ void VectorAnimationTask::Initialize()
 
 bool VectorAnimationTask::Rasterize()
 {
-  bool stopped = false, needAnimationFinishedTrigger;
+  bool stopped = false, needAnimationFinishedTrigger, resourceReady;
   uint32_t currentFrame, startFrame, endFrame;
   int32_t loopCount, currentLoopCount;
   PlayState playState;
@@ -374,6 +431,7 @@ bool VectorAnimationTask::Rasterize()
     if( mPlayState == PlayState::PLAYING && mUpdateFrameNumber )
     {
       mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1;
+      Dali::ClampInPlace( mCurrentFrame, mStartFrame, mEndFrame );
     }
 
     currentFrame = mCurrentFrame;
@@ -383,6 +441,7 @@ bool VectorAnimationTask::Rasterize()
     currentLoopCount = mCurrentLoop;
     needAnimationFinishedTrigger = mNeedAnimationFinishedTrigger;
     playState = mPlayState;
+    resourceReady = mResourceReady;
 
     mResourceReady = true;
     mCurrentFrameUpdated = false;
@@ -457,11 +516,19 @@ bool VectorAnimationTask::Rasterize()
     {
       DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Rasterize: Rendering failed. Try again later.[%d] [%p]\n", currentFrame, this );
       mUpdateFrameNumber = false;
+
+      if( !resourceReady )
+      {
+        ConditionalWait::ScopedLock lock( mConditionalWait );
+        mResourceReady = false;
+      }
     }
   }
 
   if( stopped && renderSuccess )
   {
+    ConditionalWait::ScopedLock lock( mConditionalWait );
+
     mPlayState = PlayState::STOPPED;
     mForward = true;
     mCurrentLoop = 0;