}
-int UtcDaliAnimatedImageVisualGif01(void)
+int UtcDaliAnimatedImageVisualAnimatedImage01(void)
{
ToolkitTestApplication application;
TestGlAbstraction& gl = application.GetGlAbstraction();
${toolkit_src_dir}/visuals/animated-image/image-cache.cpp
${toolkit_src_dir}/visuals/animated-image/fixed-image-cache.cpp
${toolkit_src_dir}/visuals/animated-image/rolling-image-cache.cpp
- ${toolkit_src_dir}/visuals/animated-image/rolling-gif-image-cache.cpp
+ ${toolkit_src_dir}/visuals/animated-image/rolling-animated-image-cache.cpp
${toolkit_src_dir}/visuals/animated-vector-image/animated-vector-image-visual.cpp
${toolkit_src_dir}/visuals/animated-vector-image/vector-animation-task.cpp
${toolkit_src_dir}/visuals/animated-vector-image/vector-animation-thread.cpp
#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
#include <dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h>
#include <dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h>
-#include <dali-toolkit/internal/visuals/animated-image/rolling-gif-image-cache.h>
+#include <dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.h>
#include <dali-toolkit/devel-api/image-loader/image-atlas.h>
#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties )
{
AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache, shaderFactory ) );
- visual->InitializeGif( imageUrl );
+ visual->InitializeAnimatedImage( imageUrl );
visual->SetProperties( properties );
if( visual->mFrameCount > 0 )
AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl )
{
AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache, shaderFactory ) );
- visual->InitializeGif( imageUrl );
+ visual->InitializeAnimatedImage( imageUrl );
if( visual->mFrameCount > 0 )
{
return visual;
}
-void AnimatedImageVisual::InitializeGif( const VisualUrl& imageUrl )
+void AnimatedImageVisual::InitializeAnimatedImage( const VisualUrl& imageUrl )
{
mImageUrl = imageUrl;
- mGifLoading = GifLoading::New( imageUrl.GetUrl(), imageUrl.IsLocalResource() );
- mFrameCount = mGifLoading->GetImageCount();
- mGifLoading->LoadFrameDelays( mFrameDelayContainer );
+ mAnimatedImageLoading = AnimatedImageLoading::New( imageUrl.GetUrl(), imageUrl.IsLocalResource() );
+ mFrameCount = mAnimatedImageLoading.GetImageCount();
}
AnimatedImageVisual::AnimatedImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory )
mImageVisualShaderFactory( shaderFactory ),
mPixelArea( FULL_TEXTURE_RECT ),
mImageUrl(),
- mGifLoading( nullptr ),
+ mAnimatedImageLoading(),
mCurrentFrameIndex( 0 ),
mImageUrls( NULL ),
mImageCache( NULL ),
{
if( mImageUrl.IsValid() )
{
- mImageSize = mGifLoading->GetImageSize();
+ mImageSize = mAnimatedImageLoading.GetImageSize();
}
else if( mImageUrls && mImageUrls->size() > 0 )
{
}
case DevelAnimatedImageVisual::Action::PLAY:
{
- if( IsOnStage() && mActionStatus != DevelAnimatedImageVisual::Action::PLAY )
+ if( mFrameDelayTimer && IsOnStage() && mActionStatus != DevelAnimatedImageVisual::Action::PLAY )
{
mFrameDelayTimer.Start();
}
mUrlIndex = 0;
TextureManager& textureManager = mFactoryCache.GetTextureManager();
- if( mGifLoading != nullptr )
+ if( mAnimatedImageLoading )
{
- mImageCache = new RollingGifImageCache( textureManager, *mGifLoading, mFrameCount, *this, cacheSize, batchSize );
+ mImageCache = new RollingAnimatedImageCache( textureManager, mAnimatedImageLoading, mFrameCount, *this, cacheSize, batchSize );
}
else if( mImageUrls )
{
if( mFrameCount > 1 )
{
int frameDelay = mFrameDelay; // from URL array
- if( mFrameDelayContainer.Count() > 0 ) // from GIF
+ if( mAnimatedImageLoading && mImageCache )
{
- frameDelay = mFrameDelayContainer[0];
+ frameDelay = mImageCache->GetFrameInterval( 0 );
}
-
mFrameDelayTimer = Timer::New( frameDelay );
mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame );
mFrameDelayTimer.Start();
return DisplayNextFrame();
}
}
-
- if( mFrameDelayContainer.Count() > 0 )
+ // TODO : newly added one.
+ if( mAnimatedImageLoading && mImageCache )
{
- unsigned int delay = mFrameDelayContainer[mCurrentFrameIndex];
-
+ unsigned int delay = mImageCache->GetFrameInterval( mCurrentFrameIndex );
if( mFrameDelayTimer.GetInterval() != delay )
{
mFrameDelayTimer.SetInterval( delay );
#include <dali/public-api/math/vector4.h>
#include <dali/public-api/object/weak-handle.h>
#include <dali/public-api/adaptor-framework/timer.h>
-#include <dali/devel-api/adaptor-framework/gif-loading.h>
+#include <dali/devel-api/adaptor-framework/animated-image-loading.h>
// INTERNAL INCLUDES
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
*
* @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
* @param[in] shaderFactory The ImageVisualShaderFactory object
- * @param[in] imageUrl The URL to gif resource to use
+ * @param[in] imageUrl The URL to animated image resource to use
* @param[in] properties A Property::Map containing settings for this visual
* @return A smart-pointer to the newly allocated visual.
*/
bool DisplayNextFrame();
/**
- * Initialize the gif variables.
- * @param[in] imageUrl The url of the animated gif
+ * Initialize the animated image variables.
+ * @param[in] imageUrl The url of the animated image
*/
- void InitializeGif( const VisualUrl& imageUrl );
+ void InitializeAnimatedImage( const VisualUrl& imageUrl );
// Undefined
AnimatedImageVisual( const AnimatedImageVisual& animatedImageVisual );
WeakHandle<Actor> mPlacementActor;
ImageVisualShaderFactory& mImageVisualShaderFactory;
- // Variables for GIF player
- Dali::Vector<uint32_t> mFrameDelayContainer;
+ // Variables for Animated Image player
Vector4 mPixelArea;
VisualUrl mImageUrl;
- std::unique_ptr<Dali::GifLoading> mGifLoading; // Only needed for animated gifs
+ Dali::AnimatedImageLoading mAnimatedImageLoading; // Only needed for animated image
uint32_t mCurrentFrameIndex; // Frame index into textureRects
// Variables for Multi-Image player
{
while( frameIndex > mFront )
{
- NextFrame();
+ ++mFront;
+ if( mFront >= mImageUrls.size() )
+ {
+ mFront = 0;
+ }
+ LoadBatch();
}
+
mFront = frameIndex;
TextureSet textureSet;
return textureSet;
}
-TextureSet FixedImageCache::NextFrame()
+uint32_t FixedImageCache::GetFrameInterval( uint32_t frameIndex )
{
- TextureSet textureSet;
- ++mFront;
- mFront %= mImageUrls.size();
-
- if( IsFrontReady() == true )
- {
- textureSet = GetFrontTextureSet();
- }
- else
- {
- mWaitingForReadyFrame = true;
- }
- LoadBatch();
-
- return textureSet;
+ return 0u;
}
bool FixedImageCache::IsFrontReady() const
TextureSet FirstFrame() override;
/**
- * Get the next frame. If it's not ready, this will trigger the
- * sending of FrameReady() when the image becomes ready.
- * This will trigger the loading of the next batch.
+ * Get the interval of Nth frame.
*/
- TextureSet NextFrame() override;
+ uint32_t GetFrameInterval( uint32_t frameIndex ) override;
private:
/**
virtual TextureSet FirstFrame() = 0;
/**
- * Get the next frame. If it's not ready, this will trigger the
+ * Get the Nth frame. If it's not ready, this will trigger the
* sending of FrameReady() when the image becomes ready.
- * This will trigger the loading of the next batch.
*/
- virtual TextureSet NextFrame() = 0;
+ virtual TextureSet Frame( uint32_t frameIndex ) = 0;
/**
- * Get the Nth frame. If it's not ready, this will trigger the
- * sending of FrameReady() when the image becomes ready.
+ * Get the interval of Nth frame.
*/
- virtual TextureSet Frame( uint32_t frameIndex ) = 0;
+ virtual uint32_t GetFrameInterval( uint32_t frameIndex ) = 0;
private:
*/
// CLASS HEADER
-#include "rolling-gif-image-cache.h"
+#include "rolling-animated-image-cache.h"
// EXTERNAL HEADERS
namespace Internal
{
-RollingGifImageCache::RollingGifImageCache(
- TextureManager& textureManager, GifLoading& gifLoading, uint32_t frameCount, ImageCache::FrameReadyObserver& observer,
+RollingAnimatedImageCache::RollingAnimatedImageCache(
+ TextureManager& textureManager, AnimatedImageLoading& animatedImageLoading, uint32_t frameCount, ImageCache::FrameReadyObserver& observer,
uint16_t cacheSize, uint16_t batchSize )
: ImageCache( textureManager, observer, batchSize ),
- mGifLoading( gifLoading ),
+ mAnimatedImageLoading( animatedImageLoading ),
mFrameCount( frameCount ),
mFrameIndex( 0 ),
mCacheSize( cacheSize ),
LoadBatch();
}
-RollingGifImageCache::~RollingGifImageCache()
+RollingAnimatedImageCache::~RollingAnimatedImageCache()
{
if( mTextureManagerAlive )
{
- while( !mQueue.IsEmpty() )
+ while( IsFrontReady() )
{
ImageFrame imageFrame = mQueue.PopFront();
Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
}
}
-TextureSet RollingGifImageCache::Frame( uint32_t frameIndex )
+TextureSet RollingAnimatedImageCache::Frame( uint32_t frameIndex )
{
- // If a frame of frameIndex is not loaded, clear the queue and remove all loaded textures.
- if( mImageUrls[ frameIndex ].mTextureId == TextureManager::INVALID_TEXTURE_ID )
+ bool popExist = false;
+ while( IsFrontReady() && mQueue.Front().mFrameNumber != frameIndex )
{
- mFrameIndex = frameIndex;
- while( !mQueue.IsEmpty() )
- {
- ImageFrame imageFrame = mQueue.PopFront();
- Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
- mImageUrls[ imageFrame.mFrameNumber ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
- }
- LoadBatch();
+ ImageFrame imageFrame = mQueue.PopFront();
+ Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
+ mImageUrls[ imageFrame.mFrameNumber ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
+ popExist = true;
}
- // If the frame is already loaded, remove previous frames of the frame in the queue
- // and load new frames amount of removed frames.
- else
+ if( popExist || mImageUrls[ frameIndex ].mTextureId == TextureManager::INVALID_TEXTURE_ID )
{
- bool popExist = false;
- while( !mQueue.IsEmpty() && mQueue.Front().mFrameNumber != frameIndex )
+ // If the frame of frameIndex was already loaded, load batch from the last frame of queue
+ if( IsFrontReady() )
{
- ImageFrame imageFrame = mQueue.PopFront();
- Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
- mImageUrls[ imageFrame.mFrameNumber ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
- popExist = true;
+ mFrameIndex = ( mQueue.Back().mFrameNumber + 1 ) % mFrameCount;
}
- if( popExist )
+ // If the queue is empty, load batch from the frame of frameIndex
+ else
{
- mFrameIndex = ( mQueue.Back().mFrameNumber + 1 ) % mFrameCount;
- LoadBatch();
+ mFrameIndex = frameIndex;
}
+ LoadBatch();
}
return GetFrontTextureSet();
}
-TextureSet RollingGifImageCache::FirstFrame()
+TextureSet RollingAnimatedImageCache::FirstFrame()
{
return Frame( 0u );
}
-TextureSet RollingGifImageCache::NextFrame()
+uint32_t RollingAnimatedImageCache::GetFrameInterval( uint32_t frameIndex )
{
- ImageFrame imageFrame = mQueue.PopFront();
- Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
- mImageUrls[ imageFrame.mFrameNumber ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
-
- LoadBatch();
-
- return GetFrontTextureSet();
+ Frame( frameIndex );
+ return mAnimatedImageLoading.GetFrameInterval( frameIndex );
}
-bool RollingGifImageCache::IsFrontReady() const
+bool RollingAnimatedImageCache::IsFrontReady() const
{
return ( !mQueue.IsEmpty() );
}
-void RollingGifImageCache::LoadBatch()
+void RollingAnimatedImageCache::LoadBatch()
{
// Try and load up to mBatchSize images, until the cache is filled.
// Once the cache is filled, as frames progress, the old frame is
// Get the smallest number of frames we need to load
int batchSize = std::min( std::size_t(mBatchSize), mCacheSize - mQueue.Count() );
- DALI_LOG_INFO( gAnimImgLogFilter, Debug::Concise, "RollingGifImageCache::LoadBatch() mFrameIndex:%d batchSize:%d\n", mFrameIndex, batchSize );
-
- if( mGifLoading.LoadNextNFrames( mFrameIndex, batchSize, pixelDataList) )
+ DALI_LOG_INFO( gAnimImgLogFilter, Debug::Concise, "RollingAnimatedImageCache::LoadBatch() mFrameIndex:%d batchSize:%d\n", mFrameIndex, batchSize );
+ if( mAnimatedImageLoading.LoadNextNFrames( mFrameIndex, batchSize, pixelDataList) )
{
unsigned int pixelDataListCount = pixelDataList.size();
LOG_CACHE;
}
-TextureSet RollingGifImageCache::GetFrontTextureSet() const
+TextureSet RollingAnimatedImageCache::GetFrontTextureSet() const
{
- DALI_LOG_INFO( gAnimImgLogFilter, Debug::Concise, "RollingGifImageCache::GetFrontTextureSet() FrameNumber:%d\n", mQueue[ 0 ].mFrameNumber );
+ DALI_LOG_INFO( gAnimImgLogFilter, Debug::Concise, "RollingAnimatedImageCache::GetFrontTextureSet() FrameNumber:%d\n", mQueue[ 0 ].mFrameNumber );
TextureManager::TextureId textureId = GetCachedTextureId( 0 );
return mTextureManager.GetTextureSet( textureId );
}
-TextureManager::TextureId RollingGifImageCache::GetCachedTextureId( int index ) const
+TextureManager::TextureId RollingAnimatedImageCache::GetCachedTextureId( int index ) const
{
return mImageUrls[ mQueue[ index ].mFrameNumber ].mTextureId;
}
-#ifndef DALI_TOOLKIT_INTERNAL_ROLLING_GIF_IMAGE_CACHE_H
-#define DALI_TOOLKIT_INTERNAL_ROLLING_GIF_IMAGE_CACHE_H
+#ifndef DALI_TOOLKIT_INTERNAL_ROLLING_ANIMATED_IMAGE_CACHE_H
+#define DALI_TOOLKIT_INTERNAL_ROLLING_ANIMATED_IMAGE_CACHE_H
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd.
*/
// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/gif-loading.h>
+#include <dali/devel-api/adaptor-framework/animated-image-loading.h>
#include <dali/devel-api/common/circular-queue.h>
#include <dali-toolkit/internal/visuals/animated-image/image-cache.h>
#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
{
/**
- * Class to manage a rolling cache of GIF images, where the cache size
+ * Class to manage a rolling cache of Animated images, where the cache size
* is smaller than the total number of images.
*
* Frames are always ready, so the observer.FrameReady callback is never triggered;
* the FirstFrame and NextFrame APIs will always return a texture.
*/
-class RollingGifImageCache : public ImageCache
+class RollingAnimatedImageCache : public ImageCache
{
public:
/**
* Constructor.
* @param[in] textureManager The texture manager
- * @param[in] gifLoader The loaded gif image
- * @param[in] frameCount The number of frames in the gif
+ * @param[in] animatedImageLoader The loaded animated image
+ * @param[in] frameCount The number of frames in the animated image
* @param[in] observer FrameReady observer
* @param[in] cacheSize The size of the cache
* @param[in] batchSize The size of a batch to load
* This will start loading textures immediately, according to the
* batch and cache sizes.
*/
- RollingGifImageCache( TextureManager& textureManager,
- GifLoading& gifLoader,
+ RollingAnimatedImageCache( TextureManager& textureManager,
+ AnimatedImageLoading& animatedImageLoader,
uint32_t frameCount,
ImageCache::FrameReadyObserver& observer,
uint16_t cacheSize,
/**
* Destructor
*/
- virtual ~RollingGifImageCache();
+ virtual ~RollingAnimatedImageCache();
/**
* Get the Nth frame. If it's not ready, this will trigger the
TextureSet FirstFrame() override;
/**
- * Get the next frame. If it's not ready, this will trigger the
- * sending of FrameReady() when the image becomes ready.
- * This will trigger the loading of the next batch.
+ * Get the interval of Nth frame.
*/
- TextureSet NextFrame() override;
+ uint32_t GetFrameInterval( uint32_t frameIndex ) override;
private:
/**
unsigned int mFrameNumber = 0u;
};
- GifLoading& mGifLoading;
- uint32_t mFrameCount;
- int mFrameIndex;
- std::vector<UrlStore> mImageUrls;
- uint16_t mCacheSize;
- CircularQueue<ImageFrame> mQueue;
+ Dali::AnimatedImageLoading& mAnimatedImageLoading;
+ uint32_t mFrameCount;
+ int mFrameIndex;
+ std::vector<UrlStore> mImageUrls;
+ uint16_t mCacheSize;
+ CircularQueue<ImageFrame> mQueue;
};
} // namespace Internal
+
} // namespace Toolkit
+
} // namespace Dali
-#endif
+#endif //DALI_TOOLKIT_INTERNAL_ROLLING_ANIMATED_IMAGE_CACHE_H
return Frame( 0u );
}
-TextureSet RollingImageCache::NextFrame()
+uint32_t RollingImageCache::GetFrameInterval( uint32_t frameIndex )
{
- TextureSet textureSet;
-
- ImageFrame imageFrame = mQueue.PopFront();
- mTextureManager.Remove( mImageUrls[ imageFrame.mUrlIndex ].mTextureId, this );
- mImageUrls[ imageFrame.mUrlIndex ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
-
- LoadBatch();
-
- if( IsFrontReady() == true )
- {
- textureSet = GetFrontTextureSet();
- }
- else
- {
- mWaitingForReadyFrame = true;
- }
-
- return textureSet;
+ return 0u;
}
bool RollingImageCache::IsFrontReady() const
TextureSet FirstFrame() override;
/**
- * Get the next frame. If it's not ready, this will trigger the
- * sending of FrameReady() when the image becomes ready.
- * This will trigger the loading of the next batch.
+ * Get the interval of Nth frame.
*/
- TextureSet NextFrame() override;
+ uint32_t GetFrameInterval( uint32_t frameIndex ) override;
private:
/**
break;
}
case VisualUrl::GIF:
+ case VisualUrl::WEBP:
{
visualPtr = AnimatedImageVisual::New( GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap );
break;
break;
}
case VisualUrl::GIF:
+ case VisualUrl::WEBP:
{
visualPtr = AnimatedImageVisual::New( GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl );
break;
/*
- * Copyright (c) 2017 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.
enum { SUFFIX, HASH, HASH_DOT } state = SUFFIX;
char SVG[ 4 ] = { 'g', 'v', 's', '.' };
char GIF[ 4 ] = { 'f', 'i', 'g', '.' };
+ char WEBP[ 5 ] = { 'p', 'b', 'e', 'w', '.' };
char JSON[ 5 ] = { 'n', 'o', 's', 'j', '.' };
unsigned int svgScore = 0;
unsigned int gifScore = 0;
+ unsigned int webpScore = 0;
unsigned int jsonScore = 0;
int index = count;
while( --index >= 0 )
return VisualUrl::GIF;
}
}
+ if( ( offsetFromEnd < sizeof(WEBP) )&&( currentChar == WEBP[ offsetFromEnd ] ) )
+ {
+ // early out if WEBP as can't be used in N patch for now
+ if( ++webpScore == sizeof(WEBP) )
+ {
+ return VisualUrl::WEBP;
+ }
+ }
if( ( offsetFromEnd < sizeof(JSON) )&&( currentChar == JSON[ offsetFromEnd ] ) )
{
// early out if JSON as can't be used in N patch for now
#define DALI_TOOLKIT_INTERNAL_VISUAL_URL_H
/*
- * Copyright (c) 2017 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.
N_PATCH,
SVG,
GIF,
+ WEBP,
JSON
};