}
-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:
--- /dev/null
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include "rolling-animated-image-cache.h"
+
+// EXTERNAL HEADERS
+
+// INTERNAL HEADERS
+#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
+#include <dali-toolkit/internal/visuals/image-atlas-manager.h> // For ImageAtlasManagerPtr
+#include <dali/integration-api/debug.h>
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ANIMATED_IMAGE");
+
+#define LOG_CACHE \
+ { \
+ std::ostringstream oss; \
+ oss<<"Size:"<<mQueue.Count()<<" [ "; \
+ for(std::size_t _i=0; _i<mQueue.Count(); ++_i) \
+ { \
+ oss<<_i<< \
+ "={ frm#: " << mQueue[_i].mFrameNumber << \
+ " tex: " << mImageUrls[mQueue[_i].mFrameNumber].mTextureId<<"}, "; \
+ } \
+ oss<<" ]"<<std::endl; \
+ DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"%s",oss.str().c_str()); \
+ }
+
+#else
+ #define LOG_CACHE
+#endif
+
+const bool ENABLE_ORIENTATION_CORRECTION( true );
+
+}
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+RollingAnimatedImageCache::RollingAnimatedImageCache(
+ TextureManager& textureManager, AnimatedImageLoading& animatedImageLoading, uint32_t frameCount, ImageCache::FrameReadyObserver& observer,
+ uint16_t cacheSize, uint16_t batchSize )
+: ImageCache( textureManager, observer, batchSize ),
+ mAnimatedImageLoading( animatedImageLoading ),
+ mFrameCount( frameCount ),
+ mFrameIndex( 0 ),
+ mCacheSize( cacheSize ),
+ mQueue( cacheSize )
+{
+ mImageUrls.resize( mFrameCount );
+ LoadBatch();
+}
+
+RollingAnimatedImageCache::~RollingAnimatedImageCache()
+{
+ if( mTextureManagerAlive )
+ {
+ while( IsFrontReady() )
+ {
+ ImageFrame imageFrame = mQueue.PopFront();
+ Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
+ }
+ }
+}
+
+TextureSet RollingAnimatedImageCache::Frame( uint32_t frameIndex )
+{
+ bool popExist = false;
+ while( IsFrontReady() && mQueue.Front().mFrameNumber != frameIndex )
+ {
+ ImageFrame imageFrame = mQueue.PopFront();
+ Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
+ mImageUrls[ imageFrame.mFrameNumber ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
+ popExist = true;
+ }
+ if( popExist || mImageUrls[ frameIndex ].mTextureId == TextureManager::INVALID_TEXTURE_ID )
+ {
+ // If the frame of frameIndex was already loaded, load batch from the last frame of queue
+ if( IsFrontReady() )
+ {
+ mFrameIndex = ( mQueue.Back().mFrameNumber + 1 ) % mFrameCount;
+ }
+ // If the queue is empty, load batch from the frame of frameIndex
+ else
+ {
+ mFrameIndex = frameIndex;
+ }
+ LoadBatch();
+ }
+
+ return GetFrontTextureSet();
+}
+
+TextureSet RollingAnimatedImageCache::FirstFrame()
+{
+ return Frame( 0u );
+}
+
+uint32_t RollingAnimatedImageCache::GetFrameInterval( uint32_t frameIndex )
+{
+ Frame( frameIndex );
+ return mAnimatedImageLoading.GetFrameInterval( frameIndex );
+}
+
+bool RollingAnimatedImageCache::IsFrontReady() const
+{
+ return ( !mQueue.IsEmpty() );
+}
+
+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
+ // removed, and another frame is loaded
+
+ std::vector<Dali::PixelData> pixelDataList;
+
+ // 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, "RollingAnimatedImageCache::LoadBatch() mFrameIndex:%d batchSize:%d\n", mFrameIndex, batchSize );
+ if( mAnimatedImageLoading.LoadNextNFrames( mFrameIndex, batchSize, pixelDataList) )
+ {
+ unsigned int pixelDataListCount = pixelDataList.size();
+
+ for( unsigned int i = 0; i < pixelDataListCount && !mQueue.IsFull(); ++i )
+ {
+ ImageFrame imageFrame;
+
+ // create the texture for uploading the pixel data
+ Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D,
+ pixelDataList[i].GetPixelFormat(),
+ pixelDataList[i].GetWidth(),
+ pixelDataList[i].GetHeight() );
+
+ texture.Upload( pixelDataList[i] );
+
+ mImageUrls[ mUrlIndex ].mUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
+ imageFrame.mFrameNumber = mUrlIndex;
+
+ ++mUrlIndex;
+ mUrlIndex %= mImageUrls.size();
+
+ mQueue.PushBack( imageFrame );
+
+ bool synchronousLoading = false;
+ bool atlasingStatus = false;
+ bool loadingStatus = false;
+ TextureManager::MaskingDataPointer maskInfo = nullptr;
+ AtlasUploadObserver* atlasObserver = nullptr;
+ ImageAtlasManagerPtr imageAtlasManager = nullptr;
+ Vector4 textureRect;
+ Dali::ImageDimensions textureRectSize;
+ auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
+ mTextureManager.LoadTexture(
+ mImageUrls[ imageFrame.mFrameNumber ].mUrl, ImageDimensions(), FittingMode::SCALE_TO_FILL,
+ SamplingMode::BOX_THEN_LINEAR, maskInfo,
+ synchronousLoading, mImageUrls[ imageFrame.mFrameNumber ].mTextureId, textureRect, textureRectSize,
+ atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT,
+ Dali::WrapMode::Type::DEFAULT, NULL,
+ atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply );
+ }
+
+ mFrameIndex += batchSize;
+ mFrameIndex %= mFrameCount;
+ }
+
+ LOG_CACHE;
+}
+
+TextureSet RollingAnimatedImageCache::GetFrontTextureSet() const
+{
+ 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 RollingAnimatedImageCache::GetCachedTextureId( int index ) const
+{
+ return mImageUrls[ mQueue[ index ].mFrameNumber ].mTextureId;
+}
+
+} //namespace Internal
+} //namespace Toolkit
+} //namespace Dali
--- /dev/null
+#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.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#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>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+/**
+ * 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 RollingAnimatedImageCache : public ImageCache
+{
+public:
+ /**
+ * Constructor.
+ * @param[in] textureManager The texture manager
+ * @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.
+ */
+ RollingAnimatedImageCache( TextureManager& textureManager,
+ AnimatedImageLoading& animatedImageLoader,
+ uint32_t frameCount,
+ ImageCache::FrameReadyObserver& observer,
+ uint16_t cacheSize,
+ uint16_t batchSize );
+
+ /**
+ * Destructor
+ */
+ virtual ~RollingAnimatedImageCache();
+
+ /**
+ * Get the Nth frame. If it's not ready, this will trigger the
+ * sending of FrameReady() when the image becomes ready.
+ */
+ TextureSet Frame( uint32_t frameIndex ) override;
+
+ /**
+ * Get the first frame. If it's not ready, this will trigger the
+ * sending of FrameReady() when the image becomes ready.
+ */
+ TextureSet FirstFrame() override;
+
+ /**
+ * Get the interval of Nth frame.
+ */
+ uint32_t GetFrameInterval( uint32_t frameIndex ) override;
+
+private:
+ /**
+ * @return true if the front frame is ready
+ */
+ bool IsFrontReady() const;
+
+ /**
+ * Load the next batch of images
+ */
+ void LoadBatch();
+
+ /**
+ * Get the texture set of the front frame.
+ * @return the texture set
+ */
+ TextureSet GetFrontTextureSet() const;
+
+ /**
+ * Get the texture id of the given index
+ */
+ TextureManager::TextureId GetCachedTextureId( int index ) const;
+
+private:
+ /**
+ * Secondary class to hold readiness and index into url
+ */
+ struct ImageFrame
+ {
+ unsigned int mFrameNumber = 0u;
+ };
+
+ 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 //DALI_TOOLKIT_INTERNAL_ROLLING_ANIMATED_IMAGE_CACHE_H
+++ /dev/null
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// CLASS HEADER
-#include "rolling-gif-image-cache.h"
-
-// EXTERNAL HEADERS
-
-// INTERNAL HEADERS
-#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h> // For ImageAtlasManagerPtr
-#include <dali/integration-api/debug.h>
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ANIMATED_IMAGE");
-
-#define LOG_CACHE \
- { \
- std::ostringstream oss; \
- oss<<"Size:"<<mQueue.Count()<<" [ "; \
- for(std::size_t _i=0; _i<mQueue.Count(); ++_i) \
- { \
- oss<<_i<< \
- "={ frm#: " << mQueue[_i].mFrameNumber << \
- " tex: " << mImageUrls[mQueue[_i].mFrameNumber].mTextureId<<"}, "; \
- } \
- oss<<" ]"<<std::endl; \
- DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"%s",oss.str().c_str()); \
- }
-
-#else
- #define LOG_CACHE
-#endif
-
-const bool ENABLE_ORIENTATION_CORRECTION( true );
-
-}
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-
-RollingGifImageCache::RollingGifImageCache(
- TextureManager& textureManager, GifLoading& gifLoading, uint32_t frameCount, ImageCache::FrameReadyObserver& observer,
- uint16_t cacheSize, uint16_t batchSize )
-: ImageCache( textureManager, observer, batchSize ),
- mGifLoading( gifLoading ),
- mFrameCount( frameCount ),
- mFrameIndex( 0 ),
- mCacheSize( cacheSize ),
- mQueue( cacheSize )
-{
- mImageUrls.resize( mFrameCount );
- LoadBatch();
-}
-
-RollingGifImageCache::~RollingGifImageCache()
-{
- if( mTextureManagerAlive )
- {
- while( !mQueue.IsEmpty() )
- {
- ImageFrame imageFrame = mQueue.PopFront();
- Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
- }
- }
-}
-
-TextureSet RollingGifImageCache::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 )
- {
- 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();
- }
- // If the frame is already loaded, remove previous frames of the frame in the queue
- // and load new frames amount of removed frames.
- else
- {
- bool popExist = false;
- while( !mQueue.IsEmpty() && mQueue.Front().mFrameNumber != frameIndex )
- {
- ImageFrame imageFrame = mQueue.PopFront();
- Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
- mImageUrls[ imageFrame.mFrameNumber ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
- popExist = true;
- }
- if( popExist )
- {
- mFrameIndex = ( mQueue.Back().mFrameNumber + 1 ) % mFrameCount;
- LoadBatch();
- }
- }
-
- return GetFrontTextureSet();
-}
-
-TextureSet RollingGifImageCache::FirstFrame()
-{
- return Frame( 0u );
-}
-
-TextureSet RollingGifImageCache::NextFrame()
-{
- ImageFrame imageFrame = mQueue.PopFront();
- Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
- mImageUrls[ imageFrame.mFrameNumber ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
-
- LoadBatch();
-
- return GetFrontTextureSet();
-}
-
-bool RollingGifImageCache::IsFrontReady() const
-{
- return ( !mQueue.IsEmpty() );
-}
-
-void RollingGifImageCache::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
- // removed, and another frame is loaded
-
- std::vector<Dali::PixelData> pixelDataList;
-
- // 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) )
- {
- unsigned int pixelDataListCount = pixelDataList.size();
-
- for( unsigned int i = 0; i < pixelDataListCount && !mQueue.IsFull(); ++i )
- {
- ImageFrame imageFrame;
-
- // create the texture for uploading the pixel data
- Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D,
- pixelDataList[i].GetPixelFormat(),
- pixelDataList[i].GetWidth(),
- pixelDataList[i].GetHeight() );
-
- texture.Upload( pixelDataList[i] );
-
- mImageUrls[ mUrlIndex ].mUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
- imageFrame.mFrameNumber = mUrlIndex;
-
- ++mUrlIndex;
- mUrlIndex %= mImageUrls.size();
-
- mQueue.PushBack( imageFrame );
-
- bool synchronousLoading = false;
- bool atlasingStatus = false;
- bool loadingStatus = false;
- TextureManager::MaskingDataPointer maskInfo = nullptr;
- AtlasUploadObserver* atlasObserver = nullptr;
- ImageAtlasManagerPtr imageAtlasManager = nullptr;
- Vector4 textureRect;
- Dali::ImageDimensions textureRectSize;
- auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-
- mTextureManager.LoadTexture(
- mImageUrls[ imageFrame.mFrameNumber ].mUrl, ImageDimensions(), FittingMode::SCALE_TO_FILL,
- SamplingMode::BOX_THEN_LINEAR, maskInfo,
- synchronousLoading, mImageUrls[ imageFrame.mFrameNumber ].mTextureId, textureRect, textureRectSize,
- atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT,
- Dali::WrapMode::Type::DEFAULT, NULL,
- atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply );
- }
-
- mFrameIndex += batchSize;
- mFrameIndex %= mFrameCount;
- }
-
- LOG_CACHE;
-}
-
-TextureSet RollingGifImageCache::GetFrontTextureSet() const
-{
- DALI_LOG_INFO( gAnimImgLogFilter, Debug::Concise, "RollingGifImageCache::GetFrontTextureSet() FrameNumber:%d\n", mQueue[ 0 ].mFrameNumber );
-
- TextureManager::TextureId textureId = GetCachedTextureId( 0 );
- return mTextureManager.GetTextureSet( textureId );
-}
-
-TextureManager::TextureId RollingGifImageCache::GetCachedTextureId( int index ) const
-{
- return mImageUrls[ mQueue[ index ].mFrameNumber ].mTextureId;
-}
-
-} //namespace Internal
-} //namespace Toolkit
-} //namespace Dali
+++ /dev/null
-#ifndef DALI_TOOLKIT_INTERNAL_ROLLING_GIF_IMAGE_CACHE_H
-#define DALI_TOOLKIT_INTERNAL_ROLLING_GIF_IMAGE_CACHE_H
-
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/gif-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>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-
-/**
- * Class to manage a rolling cache of GIF 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
-{
-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] 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,
- uint32_t frameCount,
- ImageCache::FrameReadyObserver& observer,
- uint16_t cacheSize,
- uint16_t batchSize );
-
- /**
- * Destructor
- */
- virtual ~RollingGifImageCache();
-
- /**
- * Get the Nth frame. If it's not ready, this will trigger the
- * sending of FrameReady() when the image becomes ready.
- */
- TextureSet Frame( uint32_t frameIndex ) override;
-
- /**
- * Get the first frame. If it's not ready, this will trigger the
- * sending of FrameReady() when the image becomes ready.
- */
- 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.
- */
- TextureSet NextFrame() override;
-
-private:
- /**
- * @return true if the front frame is ready
- */
- bool IsFrontReady() const;
-
- /**
- * Load the next batch of images
- */
- void LoadBatch();
-
- /**
- * Get the texture set of the front frame.
- * @return the texture set
- */
- TextureSet GetFrontTextureSet() const;
-
- /**
- * Get the texture id of the given index
- */
- TextureManager::TextureId GetCachedTextureId( int index ) const;
-
-private:
- /**
- * Secondary class to hold readiness and index into url
- */
- struct ImageFrame
- {
- unsigned int mFrameNumber = 0u;
- };
-
- GifLoading& mGifLoading;
- uint32_t mFrameCount;
- int mFrameIndex;
- std::vector<UrlStore> mImageUrls;
- uint16_t mCacheSize;
- CircularQueue<ImageFrame> mQueue;
-};
-
-} // namespace Internal
-} // namespace Toolkit
-} // namespace Dali
-
-#endif
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
};