(Vector) Change event processing
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-vector-image / animated-vector-image-visual.cpp
index dbbb619..453f14e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 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.
@@ -19,8 +19,9 @@
 #include <dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h>
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/common/stage.h>
+#include <dali/devel-api/common/stage.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
@@ -32,6 +33,7 @@
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
+#include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h>
 
 namespace Dali
 {
@@ -47,6 +49,23 @@ namespace
 
 const Dali::Vector4 FULL_TEXTURE_RECT( 0.f, 0.f, 1.f, 1.f );
 
+// stop behavior
+DALI_ENUM_TO_STRING_TABLE_BEGIN( STOP_BEHAVIOR )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::StopBehavior, CURRENT_FRAME )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::StopBehavior, FIRST_FRAME )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::StopBehavior, LAST_FRAME )
+DALI_ENUM_TO_STRING_TABLE_END( STOP_BEHAVIOR )
+
+// looping mode
+DALI_ENUM_TO_STRING_TABLE_BEGIN( LOOPING_MODE )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::LoopingMode, RESTART )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::LoopingMode, AUTO_REVERSE )
+DALI_ENUM_TO_STRING_TABLE_END( LOOPING_MODE )
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_VECTOR_ANIMATION" );
+#endif
+
 } // unnamed namespace
 
 AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties )
@@ -65,30 +84,52 @@ AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New( VisualFactoryCache&
 }
 
 AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl )
-: Visual::Base( factoryCache, Visual::FittingMode::FILL ),
-  mImageVisualShaderFactory( shaderFactory ),
+: Visual::Base( factoryCache, Visual::FittingMode::FILL, static_cast<Toolkit::Visual::Type>( Toolkit::DevelVisual::ANIMATED_VECTOR_IMAGE ) ),
   mUrl( imageUrl ),
-  mVectorRasterizeThread( imageUrl.GetUrl() ),
+  mAnimationData(),
+  mVectorAnimationTask( new VectorAnimationTask( factoryCache, imageUrl.GetUrl() ) ),
+  mImageVisualShaderFactory( shaderFactory ),
   mVisualSize(),
+  mVisualScale( Vector2::ONE ),
   mPlacementActor(),
-  mActionStatus( DevelAnimatedVectorImageVisual::Action::STOP )
+  mPlayState( DevelImageVisual::PlayState::STOPPED ),
+  mEventCallback( nullptr ),
+  mRendererAdded( false )
 {
   // the rasterized image is with pre-multiplied alpha format
   mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
 
-  mVectorRasterizeThread.SetResourceReadyCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnResourceReady ) ) );
-  mVectorRasterizeThread.SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) );
-
-  mVectorRasterizeThread.Start();
+  mVectorAnimationTask->UploadCompletedSignal().Connect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
+  mVectorAnimationTask->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) );
 }
 
 AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
 {
+  if( mEventCallback )
+  {
+    mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback( mEventCallback );
+  }
+
+  // Finalize animation task and disconnect the signal in the main thread
+  mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
+  mVectorAnimationTask->Finalize();
 }
 
 void AnimatedVectorImageVisual::GetNaturalSize( Vector2& naturalSize )
 {
-  naturalSize = mVisualSize;
+  if( mVisualSize != Vector2::ZERO )
+  {
+    naturalSize = mVisualSize;
+  }
+  else
+  {
+    uint32_t width, height;
+    mVectorAnimationTask->GetDefaultSize( width, height );
+    naturalSize.x = width;
+    naturalSize.y = height;
+  }
+
+  DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::GetNaturalSize: w = %f, h = %f [%p]\n", naturalSize.width, naturalSize.height, this );
 }
 
 void AnimatedVectorImageVisual::DoCreatePropertyMap( Property::Map& map ) const
@@ -99,9 +140,26 @@ void AnimatedVectorImageVisual::DoCreatePropertyMap( Property::Map& map ) const
   {
     map.Insert( Toolkit::ImageVisual::Property::URL, mUrl.GetUrl() );
   }
-  map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast< int >( mVectorRasterizeThread.GetLoopCount() ) );
-  map.Insert( Toolkit::DevelImageVisual::Property::PLAY_RANGE, static_cast< Vector2 >( mVectorRasterizeThread.GetPlayRange() ) );
-  map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int >( mVectorRasterizeThread.GetPlayState() ) );
+  map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, mAnimationData.loopCount );
+
+  uint32_t startFrame, endFrame;
+  mVectorAnimationTask->GetPlayRange( startFrame, endFrame );
+
+  Property::Array playRange;
+  playRange.PushBack( static_cast< int32_t >( startFrame ) );
+  playRange.PushBack( static_cast< int32_t >( endFrame ) );
+  map.Insert( Toolkit::DevelImageVisual::Property::PLAY_RANGE, playRange );
+
+  map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int32_t >( mPlayState ) );
+  map.Insert( Toolkit::DevelImageVisual::Property::CURRENT_FRAME_NUMBER, static_cast< int32_t >( mVectorAnimationTask->GetCurrentFrameNumber() ) );
+  map.Insert( Toolkit::DevelImageVisual::Property::TOTAL_FRAME_NUMBER, static_cast< int32_t >( mVectorAnimationTask->GetTotalFrameNumber() ) );
+
+  map.Insert( Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, mAnimationData.stopBehavior );
+  map.Insert( Toolkit::DevelImageVisual::Property::LOOPING_MODE, mAnimationData.loopingMode );
+
+  Property::Map layerInfo;
+  mVectorAnimationTask->GetLayerInfo( layerInfo );
+  map.Insert( Toolkit::DevelImageVisual::Property::CONTENT_INFO, layerInfo );
 }
 
 void AnimatedVectorImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
@@ -129,8 +187,18 @@ void AnimatedVectorImageVisual::DoSetProperties( const Property::Map& propertyMa
        {
           DoSetProperty( Toolkit::DevelImageVisual::Property::PLAY_RANGE, keyValue.second );
        }
+       else if( keyValue.first == STOP_BEHAVIOR_NAME )
+       {
+          DoSetProperty( Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, keyValue.second );
+       }
+       else if( keyValue.first == LOOPING_MODE_NAME )
+       {
+          DoSetProperty( Toolkit::DevelImageVisual::Property::LOOPING_MODE, keyValue.second );
+       }
     }
   }
+
+  TriggerVectorRasterization();
 }
 
 void AnimatedVectorImageVisual::DoSetProperty( Property::Index index, const Property::Value& value )
@@ -142,23 +210,45 @@ void AnimatedVectorImageVisual::DoSetProperty( Property::Index index, const Prop
       int32_t loopCount;
       if( value.Get( loopCount ) )
       {
-        mVectorRasterizeThread.SetLoopCount( loopCount );
+        mAnimationData.loopCount = loopCount;
+        mAnimationData.resendFlag |= VectorAnimationTask::RESEND_LOOP_COUNT;
       }
       break;
     }
     case Toolkit::DevelImageVisual::Property::PLAY_RANGE:
     {
-      Vector2 range;
-      if( value.Get( range ) )
+      Property::Array* array = value.GetArray();
+      if( array )
+      {
+        mAnimationData.playRange = *array;
+        mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_RANGE;
+      }
+      break;
+    }
+    case Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR:
+    {
+      int32_t stopBehavior = mAnimationData.stopBehavior;
+      if( Scripting::GetEnumerationProperty( value, STOP_BEHAVIOR_TABLE, STOP_BEHAVIOR_TABLE_COUNT, stopBehavior ) )
       {
-        mVectorRasterizeThread.SetPlayRange( range );
+        mAnimationData.stopBehavior = DevelImageVisual::StopBehavior::Type( stopBehavior );
+        mAnimationData.resendFlag |= VectorAnimationTask::RESEND_STOP_BEHAVIOR;
+      }
+      break;
+    }
+    case Toolkit::DevelImageVisual::Property::LOOPING_MODE:
+    {
+      int32_t loopingMode = mAnimationData.loopingMode;
+      if( Scripting::GetEnumerationProperty( value, LOOPING_MODE_TABLE, LOOPING_MODE_TABLE_COUNT, loopingMode ) )
+      {
+        mAnimationData.loopingMode = DevelImageVisual::LoopingMode::Type( loopingMode );
+        mAnimationData.resendFlag |= VectorAnimationTask::RESEND_LOOPING_MODE;
       }
       break;
     }
   }
 }
 
-void AnimatedVectorImageVisual::DoSetOnStage( Actor& actor )
+void AnimatedVectorImageVisual::DoSetOnScene( Actor& actor )
 {
   Shader shader;
 
@@ -172,7 +262,7 @@ void AnimatedVectorImageVisual::DoSetOnStage( Actor& actor )
   }
   else
   {
-    shader = mImageVisualShaderFactory.GetShader( mFactoryCache, false, true );
+    shader = mImageVisualShaderFactory.GetShader( mFactoryCache, false, true, false );
   }
 
   Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
@@ -190,68 +280,79 @@ void AnimatedVectorImageVisual::DoSetOnStage( Actor& actor )
   // Hold the weak handle of the placement actor and delay the adding of renderer until the rasterization is finished.
   mPlacementActor = actor;
 
-  mVectorRasterizeThread.SetRenderer( mImpl->mRenderer );
+  mVectorAnimationTask->SetRenderer( mImpl->mRenderer );
+
+  // Add property notification for scaling & size
+  mScaleNotification = actor.AddPropertyNotification( Actor::Property::WORLD_SCALE, StepCondition( 0.1f, 1.0f ) );
+  mScaleNotification.NotifySignal().Connect( this, &AnimatedVectorImageVisual::OnScaleNotification );
+
+  mSizeNotification = actor.AddPropertyNotification( Actor::Property::SIZE, StepCondition( 3.0f ) );
+  mSizeNotification.NotifySignal().Connect( this, &AnimatedVectorImageVisual::OnSizeNotification );
+
+  DevelActor::VisibilityChangedSignal( actor ).Connect( this, &AnimatedVectorImageVisual::OnControlVisibilityChanged );
+
+  Window window = DevelWindow::Get( actor );
+  if( window )
+  {
+    DevelWindow::VisibilityChangedSignal( window ).Connect( this, &AnimatedVectorImageVisual::OnWindowVisibilityChanged );
+  }
+
+  DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::DoSetOnScene [%p]\n", this );
 }
 
-void AnimatedVectorImageVisual::DoSetOffStage( Actor& actor )
+void AnimatedVectorImageVisual::DoSetOffScene( Actor& actor )
 {
-  mVectorRasterizeThread.PauseAnimation();
-
-  mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE;
+  StopAnimation();
+  SendAnimationData();
 
   if( mImpl->mRenderer )
   {
-    mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED );
-
     actor.RemoveRenderer( mImpl->mRenderer );
     mImpl->mRenderer.Reset();
+
+    mRendererAdded = false;
+  }
+
+  // Remove property notification
+  actor.RemovePropertyNotification( mScaleNotification );
+  actor.RemovePropertyNotification( mSizeNotification );
+
+  DevelActor::VisibilityChangedSignal( actor ).Disconnect( this, &AnimatedVectorImageVisual::OnControlVisibilityChanged );
+
+  Window window = DevelWindow::Get( actor );
+  if( window )
+  {
+    DevelWindow::VisibilityChangedSignal( window ).Disconnect( this, &AnimatedVectorImageVisual::OnWindowVisibilityChanged );
   }
 
   mPlacementActor.Reset();
 
   // Reset the visual size to zero so that when adding the actor back to stage the rasterization is forced
   mVisualSize = Vector2::ZERO;
+  mVisualScale = Vector2::ONE;
+
+  DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::DoSetOffScene [%p]\n", this );
 }
 
 void AnimatedVectorImageVisual::OnSetTransform()
 {
   Vector2 visualSize = mImpl->mTransform.GetVisualSize( mImpl->mControlSize );
 
-  if( IsOnStage() )
+  if( IsOnScene() && visualSize != mVisualSize )
   {
-    if( visualSize != mVisualSize )
-    {
-      mVisualSize = visualSize;
-
-      uint32_t width = static_cast< uint32_t >( visualSize.width );
-      uint32_t height = static_cast< uint32_t >( visualSize.height );
+    DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnSetTransform: width = %f, height = %f [%p]\n", visualSize.width, visualSize.height, this );
 
-      mVectorRasterizeThread.SetSize( width, height );
-    }
+    mVisualSize = visualSize;
 
-    if( mActionStatus == DevelAnimatedVectorImageVisual::Action::PLAY )
-    {
-      mVectorRasterizeThread.PlayAnimation();
+    SetVectorImageSize();
 
-      mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY );
-    }
-    else
+    if( mPlayState == DevelImageVisual::PlayState::PLAYING && mAnimationData.playState != DevelImageVisual::PlayState::PLAYING )
     {
-      // Render one frame
-      mVectorRasterizeThread.RenderFrame();
+      mAnimationData.playState = DevelImageVisual::PlayState::PLAYING;
+      mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE;
     }
 
-    if( mVectorRasterizeThread.IsResourceReady() )
-    {
-      Actor actor = mPlacementActor.GetHandle();
-      if( actor )
-      {
-        actor.AddRenderer( mImpl->mRenderer );
-        mPlacementActor.Reset();
-      }
-
-      ResourceReady( Toolkit::Visual::ResourceStatus::READY );
-    }
+    SendAnimationData();
   }
 }
 
@@ -262,63 +363,91 @@ void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, cons
   {
     case DevelAnimatedVectorImageVisual::Action::PLAY:
     {
-      if( IsOnStage() )
+      if( IsOnScene() && mVisualSize != Vector2::ZERO )
       {
-        mVectorRasterizeThread.PlayAnimation();
-
-        mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY );
+        if( mAnimationData.playState != DevelImageVisual::PlayState::PLAYING )
+        {
+          mAnimationData.playState = DevelImageVisual::PlayState::PLAYING;
+          mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE;
+        }
       }
-      mActionStatus = DevelAnimatedVectorImageVisual::Action::PLAY;
+      mPlayState = DevelImageVisual::PlayState::PLAYING;
       break;
     }
     case DevelAnimatedVectorImageVisual::Action::PAUSE:
     {
-      mVectorRasterizeThread.PauseAnimation();
-
-      if( mImpl->mRenderer )
+      if( mAnimationData.playState == DevelImageVisual::PlayState::PLAYING )
       {
-        mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED );
+        mAnimationData.playState = DevelImageVisual::PlayState::PAUSED;
+        mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE;
       }
-
-      mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE;
+      mPlayState = DevelImageVisual::PlayState::PAUSED;
       break;
     }
     case DevelAnimatedVectorImageVisual::Action::STOP:
     {
-      if( mVectorRasterizeThread.GetPlayState() != DevelImageVisual::PlayState::STOPPED )
+      if( mAnimationData.playState != DevelImageVisual::PlayState::STOPPED )
       {
-        mVectorRasterizeThread.StopAnimation();
-
-        OnAnimationFinished();
+        mAnimationData.playState = DevelImageVisual::PlayState::STOPPED;
+        mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE;
+      }
+      mPlayState = DevelImageVisual::PlayState::STOPPED;
+      break;
+    }
+    case DevelAnimatedVectorImageVisual::Action::JUMP_TO:
+    {
+      int32_t frameNumber;
+      if( attributes.Get( frameNumber ) )
+      {
+        mAnimationData.currentFrame = frameNumber;
+        mAnimationData.resendFlag |= VectorAnimationTask::RESEND_CURRENT_FRAME;
+      }
+      break;
+    }
+    case DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY:
+    {
+      Property::Map* map = attributes.GetMap();
+      if( map )
+      {
+        DoSetProperties( *map );
       }
-      mActionStatus = DevelAnimatedVectorImageVisual::Action::STOP;
       break;
     }
   }
+
+  TriggerVectorRasterization();
 }
 
-void AnimatedVectorImageVisual::OnResourceReady()
+void AnimatedVectorImageVisual::OnUploadCompleted()
 {
   // If weak handle is holding a placement actor, it is the time to add the renderer to actor.
   Actor actor = mPlacementActor.GetHandle();
-  if( actor )
+  if( actor && !mRendererAdded )
   {
     actor.AddRenderer( mImpl->mRenderer );
-    // reset the weak handle so that the renderer only get added to actor once
-    mPlacementActor.Reset();
-  }
+    mRendererAdded = true;
+
+    ResourceReady( Toolkit::Visual::ResourceStatus::READY );
 
-  ResourceReady( Toolkit::Visual::ResourceStatus::READY );
+    DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnUploadCompleted: Renderer is added [%p]\n", this );
+  }
 }
 
 void AnimatedVectorImageVisual::OnAnimationFinished()
 {
-  if( mImpl->mEventObserver )
+  DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnAnimationFinished: action state = %d [%p]\n", mPlayState, this );
+
+  if( mPlayState != DevelImageVisual::PlayState::STOPPED )
   {
-    mImpl->mEventObserver->NotifyVisualEvent( *this, DevelAnimatedVectorImageVisual::Signal::ANIMATION_FINISHED );
-  }
+    mPlayState = DevelImageVisual::PlayState::STOPPED;
 
-  mActionStatus = DevelAnimatedVectorImageVisual::Action::STOP;
+    mAnimationData.playState = DevelImageVisual::PlayState::STOPPED;
+
+    if( mImpl->mEventObserver )
+    {
+      mImpl->mEventObserver->NotifyVisualEvent( *this, DevelAnimatedVectorImageVisual::Signal::ANIMATION_FINISHED );
+    }
+  }
 
   if( mImpl->mRenderer )
   {
@@ -326,6 +455,124 @@ void AnimatedVectorImageVisual::OnAnimationFinished()
   }
 }
 
+void AnimatedVectorImageVisual::SendAnimationData()
+{
+  if( mAnimationData.resendFlag )
+  {
+    mVectorAnimationTask->SetAnimationData( mAnimationData );
+
+    if( mImpl->mRenderer )
+    {
+      if( mAnimationData.playState == DevelImageVisual::PlayState::PLAYING )
+      {
+        mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY );
+      }
+      else
+      {
+        mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED );
+      }
+    }
+
+    mAnimationData.resendFlag = 0;
+  }
+}
+
+void AnimatedVectorImageVisual::SetVectorImageSize()
+{
+  uint32_t width = static_cast< uint32_t >( mVisualSize.width * mVisualScale.width );
+  uint32_t height = static_cast< uint32_t >( mVisualSize.height * mVisualScale.height );
+
+  mAnimationData.width = width;
+  mAnimationData.height = height;
+  mAnimationData.resendFlag |= VectorAnimationTask::RESEND_SIZE;
+}
+
+void AnimatedVectorImageVisual::StopAnimation()
+{
+  if( mAnimationData.playState != DevelImageVisual::PlayState::STOPPED )
+  {
+    mAnimationData.playState = DevelImageVisual::PlayState::STOPPED;
+    mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE;
+
+    mPlayState = DevelImageVisual::PlayState::STOPPED;
+  }
+}
+
+void AnimatedVectorImageVisual::TriggerVectorRasterization()
+{
+  if( !mEventCallback )
+  {
+    mEventCallback = MakeCallback( this, &AnimatedVectorImageVisual::OnProcessEvents );
+    mFactoryCache.GetVectorAnimationManager().RegisterEventCallback( mEventCallback );
+    Stage::GetCurrent().KeepRendering( 0.0f );  // Trigger event processing
+  }
+}
+
+void AnimatedVectorImageVisual::OnScaleNotification( PropertyNotification& source )
+{
+  Actor actor = mPlacementActor.GetHandle();
+  if( actor )
+  {
+    Vector3 scale = actor.GetProperty< Vector3 >( Actor::Property::WORLD_SCALE );
+    mVisualScale.width = scale.width;
+    mVisualScale.height = scale.height;
+
+    DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnScaleNotification: scale = %f, %f [%p]\n", mVisualScale.width, mVisualScale.height, this );
+
+    SetVectorImageSize();
+    SendAnimationData();
+
+    Stage::GetCurrent().KeepRendering( 0.0f );  // Trigger event processing
+  }
+}
+
+void AnimatedVectorImageVisual::OnSizeNotification( PropertyNotification& source )
+{
+  Actor actor = mPlacementActor.GetHandle();
+  if( actor )
+  {
+    Vector3 size = actor.GetCurrentProperty< Vector3 >( Actor::Property::SIZE );
+    mVisualSize.width = size.width;
+    mVisualSize.height = size.height;
+
+    DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnSizeNotification: size = %f, %f [%p]\n", mVisualSize.width, mVisualSize.height, this );
+
+    SetVectorImageSize();
+    SendAnimationData();
+
+    Stage::GetCurrent().KeepRendering( 0.0f );  // Trigger event processing
+  }
+}
+
+void AnimatedVectorImageVisual::OnControlVisibilityChanged( Actor actor, bool visible, DevelActor::VisibilityChange::Type type )
+{
+  if( !visible )
+  {
+    StopAnimation();
+    TriggerVectorRasterization();
+
+    DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnControlVisibilityChanged: invisibile. Pause animation [%p]\n", this );
+  }
+}
+
+void AnimatedVectorImageVisual::OnWindowVisibilityChanged( Window window, bool visible )
+{
+  if( !visible )
+  {
+    StopAnimation();
+    TriggerVectorRasterization();
+
+    DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnWindowVisibilityChanged: invisibile. Pause animation [%p]\n", this );
+  }
+}
+
+void AnimatedVectorImageVisual::OnProcessEvents()
+{
+  SendAnimationData();
+
+  mEventCallback = nullptr;  // The callback will be deleted in the VectorAnimationManager
+}
+
 } // namespace Internal
 
 } // namespace Toolkit