X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fanimated-image%2Fanimated-image-visual.cpp;h=b1463bad78a99d879edf51b4703ad23a9ec76650;hp=be736e16b35e3abfadedd48021ed8dfdd748446e;hb=15db27e5f16067b87796438187ba7298cc8acc1e;hpb=46322a558e537267a6d3c48630c45afca91b5e27 diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp old mode 100644 new mode 100755 index be736e1..b1463ba --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 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,22 +19,24 @@ #include "animated-image-visual.h" // EXTERNAL INCLUDES -#include #include #include +#include // INTERNAL INCLUDES #include -#include -#include +#include #include #include #include #include +#include #include #include -#include +#include #include +#include +#include namespace Dali { @@ -56,6 +58,7 @@ DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, MIRRORED_REPEAT ) DALI_ENUM_TO_STRING_TABLE_END( WRAP_MODE ) const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); +constexpr auto LOOP_FOREVER = -1; #if defined(DEBUG_ENABLED) Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ANIMATED_IMAGE"); @@ -66,12 +69,17 @@ Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, " /** * Multi-image Flow of execution * - * | DoSetProperties() + * | New + * | DoSetProperties() * | LoadFirstBatch() - * | cache->LoadBatch() + * | new cache + * | cache->LoadBatch() * | * | DoSetOnStage() + * | PrepareTextureSet() + * | cache->FirstFrame() * | CreateRenderer() (Doesn't become ready until first frame loads) + * | StartFirstFrame() * | * | FrameReady(textureSet) * | start first frame: @@ -93,18 +101,23 @@ Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, " * Time */ -AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl, const Property::Map& properties ) +AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties ) { - AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache ); - visual->mImageUrl = imageUrl; + AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache, shaderFactory ) ); + visual->InitializeGif( imageUrl ); visual->SetProperties( properties ); + if( visual->mFrameCount > 0 ) + { + visual->LoadFirstBatch(); + } + return visual; } -AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const Property::Array& imageUrls, const Property::Map& properties ) +AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Property::Array& imageUrls, const Property::Map& properties ) { - AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache ); + AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache, shaderFactory ) ); visual->mImageUrls = new ImageCache::UrlList(); visual->mImageUrls->reserve( imageUrls.Count() ); @@ -115,36 +128,60 @@ AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCach urlStore.mUrl = imageUrls[i].Get(); visual->mImageUrls->push_back( urlStore ); } - + visual->mFrameCount = imageUrls.Count(); visual->SetProperties( properties ); - // starts loading immediately + + if( visual->mFrameCount > 0 ) + { + visual->LoadFirstBatch(); + } + return visual; } -AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl ) +AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl ) { - AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache ); - visual->mImageUrl = imageUrl; + AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache, shaderFactory ) ); + visual->InitializeGif( imageUrl ); + + if( visual->mFrameCount > 0 ) + { + visual->LoadFirstBatch(); + } return visual; } -AnimatedImageVisual::AnimatedImageVisual( VisualFactoryCache& factoryCache ) -: Visual::Base( factoryCache ), +void AnimatedImageVisual::InitializeGif( const VisualUrl& imageUrl ) +{ + mImageUrl = imageUrl; + mGifLoading = GifLoading::New( imageUrl.GetUrl(), imageUrl.IsLocalResource() ); + mFrameCount = mGifLoading->GetImageCount(); + mGifLoading->LoadFrameDelays( mFrameDelayContainer ); +} + +AnimatedImageVisual::AnimatedImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory ) +: Visual::Base( factoryCache, Visual::FittingMode::FIT_KEEP_ASPECT_RATIO ), mFrameDelayTimer(), mPlacementActor(), + mImageVisualShaderFactory( shaderFactory ), mPixelArea( FULL_TEXTURE_RECT ), mImageUrl(), + mGifLoading( nullptr ), mCurrentFrameIndex( 0 ), mImageUrls( NULL ), mImageCache( NULL ), mCacheSize( 1 ), mBatchSize( 1 ), mFrameDelay( 100 ), + mLoopCount( LOOP_FOREVER ), + mCurrentLoopIndex( 0 ), mUrlIndex( 0 ), + mFrameCount( 0 ), mImageSize(), mWrapModeU( WrapMode::DEFAULT ), mWrapModeV( WrapMode::DEFAULT ), + mActionStatus( DevelAnimatedImageVisual::Action::PLAY ), mStartFirstFrame(false) {} @@ -160,7 +197,7 @@ void AnimatedImageVisual::GetNaturalSize( Vector2& naturalSize ) { if( mImageUrl.IsValid() ) { - mImageSize = Dali::GetGifImageSize( mImageUrl.GetUrl() ); + mImageSize = mGifLoading->GetImageSize(); } else if( mImageUrls && mImageUrls->size() > 0 ) { @@ -176,7 +213,7 @@ void AnimatedImageVisual::DoCreatePropertyMap( Property::Map& map ) const { map.Clear(); - map.Insert( Toolkit::DevelVisual::Property::TYPE, Toolkit::DevelVisual::ANIMATED_IMAGE ); + map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::ANIMATED_IMAGE ); if( mImageUrl.IsValid() ) { @@ -197,9 +234,10 @@ void AnimatedImageVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_U, mWrapModeU ); map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_V, mWrapModeV ); - map.Insert( Toolkit::DevelImageVisual::Property::BATCH_SIZE, static_cast(mBatchSize) ); - map.Insert( Toolkit::DevelImageVisual::Property::CACHE_SIZE, static_cast(mCacheSize) ); - map.Insert( Toolkit::DevelImageVisual::Property::FRAME_DELAY, static_cast(mFrameDelay) ); + map.Insert( Toolkit::ImageVisual::Property::BATCH_SIZE, static_cast(mBatchSize) ); + map.Insert( Toolkit::ImageVisual::Property::CACHE_SIZE, static_cast(mCacheSize) ); + map.Insert( Toolkit::ImageVisual::Property::FRAME_DELAY, static_cast(mFrameDelay) ); + map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast(mLoopCount) ); } void AnimatedImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const @@ -207,6 +245,38 @@ void AnimatedImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) cons // Do nothing } +void AnimatedImageVisual::OnDoAction( const Dali::Property::Index actionId, const Dali::Property::Value& attributes ) +{ + // Check if action is valid for this visual type and perform action if possible + + switch ( actionId ) + { + case DevelAnimatedImageVisual::Action::PAUSE: + { + // Pause will be executed on next timer tick + mActionStatus = DevelAnimatedImageVisual::Action::PAUSE; + break; + } + case DevelAnimatedImageVisual::Action::PLAY: + { + if( IsOnStage() && mActionStatus != DevelAnimatedImageVisual::Action::PLAY ) + { + mFrameDelayTimer.Start(); + } + mActionStatus = DevelAnimatedImageVisual::Action::PLAY; + break; + } + case DevelAnimatedImageVisual::Action::STOP: + { + // STOP reset functionality will actually be done in a future change + // Stop will be executed on next timer tick + mCurrentFrameIndex = 0; + mActionStatus = DevelAnimatedImageVisual::Action::STOP; + break; + } + } +} + void AnimatedImageVisual::DoSetProperties( const Property::Map& propertyMap ) { // url[s] already passed in from constructor @@ -234,23 +304,22 @@ void AnimatedImageVisual::DoSetProperties( const Property::Map& propertyMap ) } else if( keyValue.first == BATCH_SIZE_NAME ) { - DoSetProperty( Toolkit::DevelImageVisual::Property::BATCH_SIZE, keyValue.second ); + DoSetProperty( Toolkit::ImageVisual::Property::BATCH_SIZE, keyValue.second ); } else if( keyValue.first == CACHE_SIZE_NAME ) { - DoSetProperty( Toolkit::DevelImageVisual::Property::CACHE_SIZE, keyValue.second ); + DoSetProperty( Toolkit::ImageVisual::Property::CACHE_SIZE, keyValue.second ); } else if( keyValue.first == FRAME_DELAY_NAME ) { - DoSetProperty( Toolkit::DevelImageVisual::Property::FRAME_DELAY, keyValue.second ); + DoSetProperty( Toolkit::ImageVisual::Property::FRAME_DELAY, keyValue.second ); + } + else if( keyValue.first == LOOP_COUNT_NAME ) + { + DoSetProperty( Toolkit::DevelImageVisual::Property::LOOP_COUNT, keyValue.second ); } } } - - if( mImageUrls && mImageUrls->size() > 0 ) - { - LoadFirstBatch(); - } } void AnimatedImageVisual::DoSetProperty( Property::Index index, @@ -265,20 +334,32 @@ void AnimatedImageVisual::DoSetProperty( Property::Index index, } case Toolkit::ImageVisual::Property::WRAP_MODE_U: { - int wrapMode; - Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode ); - mWrapModeU = Dali::WrapMode::Type( wrapMode ); + int wrapMode = 0; + if(Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode )) + { + mWrapModeU = Dali::WrapMode::Type(wrapMode); + } + else + { + mWrapModeU = Dali::WrapMode::Type::DEFAULT; + } break; } case Toolkit::ImageVisual::Property::WRAP_MODE_V: { - int wrapMode; - Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode ); - mWrapModeV = Dali::WrapMode::Type( wrapMode ); + int wrapMode = 0; + if(Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode )) + { + mWrapModeV = Dali::WrapMode::Type(wrapMode); + } + else + { + mWrapModeV = Dali::WrapMode::Type::DEFAULT; + } break; } - case Toolkit::DevelImageVisual::Property::BATCH_SIZE: + case Toolkit::ImageVisual::Property::BATCH_SIZE: { int batchSize; if( value.Get( batchSize ) ) @@ -288,7 +369,7 @@ void AnimatedImageVisual::DoSetProperty( Property::Index index, break; } - case Toolkit::DevelImageVisual::Property::CACHE_SIZE: + case Toolkit::ImageVisual::Property::CACHE_SIZE: { int cacheSize; if( value.Get( cacheSize ) ) @@ -298,7 +379,7 @@ void AnimatedImageVisual::DoSetProperty( Property::Index index, break; } - case Toolkit::DevelImageVisual::Property::FRAME_DELAY: + case Toolkit::ImageVisual::Property::FRAME_DELAY: { int frameDelay; if( value.Get( frameDelay ) ) @@ -307,6 +388,16 @@ void AnimatedImageVisual::DoSetProperty( Property::Index index, } break; } + + case Toolkit::DevelImageVisual::Property::LOOP_COUNT: + { + int loopCount; + if( value.Get( loopCount ) ) + { + mLoopCount = loopCount; + } + break; + } } } @@ -336,9 +427,6 @@ void AnimatedImageVisual::DoSetOffStage( Actor& actor ) mFrameDelayTimer.Reset(); } - mTextureRectContainer.Clear(); - mFrameDelayContainer.Clear(); - actor.RemoveRenderer( mImpl->mRenderer ); mImpl->mRenderer.Reset(); mPlacementActor.Reset(); @@ -355,8 +443,8 @@ void AnimatedImageVisual::OnSetTransform() void AnimatedImageVisual::CreateRenderer() { bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE; - bool atlasing = (mTextureRectContainer.Count() > 0) ; - Shader shader = ImageVisual::GetImageShader( mFactoryCache, atlasing, defaultWrapMode ); + bool atlasing = false; + Shader shader = mImageVisualShaderFactory.GetShader( mFactoryCache, atlasing, defaultWrapMode, IsRoundedCornerRequired() ); Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); @@ -378,40 +466,59 @@ void AnimatedImageVisual::CreateRenderer() } mCurrentFrameIndex = 0; - - if( mTextureRectContainer.Count() > 0 ) - { - mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mTextureRectContainer[mCurrentFrameIndex] ); - } } void AnimatedImageVisual::LoadFirstBatch() { - DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::LoadFirstBatch()\n"); - // Ensure the batch size and cache size are no bigger than the number of URLs, // and that the cache is at least as big as the batch size. - uint16_t numUrls = mImageUrls->size(); - uint16_t batchSize = std::min( mBatchSize, numUrls ); - uint16_t cacheSize = std::min( std::max( batchSize, mCacheSize ), numUrls ); + uint16_t numUrls = 0; + uint16_t batchSize = 1; + uint16_t cacheSize = 1; + + if( mImageUrls ) + { + numUrls = mImageUrls->size(); + } + else + { + numUrls = mFrameCount; + } + + batchSize = std::min( mBatchSize, numUrls ); + cacheSize = std::min( std::max( batchSize, mCacheSize ), numUrls ); + + DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::LoadFirstBatch() batchSize:%d cacheSize:%d\n", batchSize, cacheSize); mUrlIndex = 0; TextureManager& textureManager = mFactoryCache.GetTextureManager(); - if( batchSize > 0 && cacheSize > 0 ) + if( mGifLoading != nullptr ) { - if( cacheSize < numUrls ) + mImageCache = new RollingGifImageCache( textureManager, *mGifLoading, mFrameCount, *this, cacheSize, batchSize ); + } + else if( mImageUrls ) + { + if( batchSize > 0 && cacheSize > 0 ) { - mImageCache = new RollingImageCache( textureManager, *mImageUrls, *this, cacheSize, batchSize ); + if( cacheSize < numUrls ) + { + mImageCache = new RollingImageCache( textureManager, *mImageUrls, *this, cacheSize, batchSize ); + } + else + { + mImageCache = new FixedImageCache( textureManager, *mImageUrls, *this, batchSize ); + } } else { - mImageCache = new FixedImageCache( textureManager, *mImageUrls, *this, batchSize ); + mImageCache = new RollingImageCache( textureManager, *mImageUrls, *this, 1, 1 ); } } - else + + if (!mImageCache) { - mImageCache = new RollingImageCache( textureManager, *mImageUrls, *this, 1, 1 ); + DALI_LOG_ERROR("mImageCache is null"); } } @@ -420,7 +527,10 @@ void AnimatedImageVisual::StartFirstFrame( TextureSet& textureSet ) DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::StartFirstFrame()\n"); mStartFirstFrame = false; - mImpl->mRenderer.SetTextures( textureSet ); + if(mImpl->mRenderer) + { + mImpl->mRenderer.SetTextures( textureSet ); + } Actor actor = mPlacementActor.GetHandle(); if( actor ) { @@ -428,55 +538,37 @@ void AnimatedImageVisual::StartFirstFrame( TextureSet& textureSet ) mPlacementActor.Reset(); } - int frameDelay = mFrameDelay; - if( mFrameDelayContainer.Count() > 1 ) + mCurrentFrameIndex = 0; + + if( mFrameCount > 1 ) { - frameDelay = mFrameDelayContainer[0]; - } - mFrameDelayTimer = Timer::New( frameDelay ); - mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame ); - mFrameDelayTimer.Start(); + int frameDelay = mFrameDelay; // from URL array + if( mFrameDelayContainer.Count() > 0 ) // from GIF + { + frameDelay = mFrameDelayContainer[0]; + } - DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"ResourceReady()\n"); - ResourceReady(); + mFrameDelayTimer = Timer::New( frameDelay ); + mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame ); + mFrameDelayTimer.Start(); + } + DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"ResourceReady(ResourceStatus::READY)\n"); + ResourceReady( Toolkit::Visual::ResourceStatus::READY ); } TextureSet AnimatedImageVisual::PrepareTextureSet() { TextureSet textureSet; - if( mImageUrl.IsValid() ) + if (mImageCache) + textureSet = mImageCache->FirstFrame(); + if( textureSet ) { - textureSet = PrepareAnimatedGifImage(); + SetImageSize( textureSet ); } else { - textureSet = mImageCache->FirstFrame(); - if( textureSet ) - { - SetImageSize( textureSet ); - } - } - return textureSet; -} - -TextureSet AnimatedImageVisual::PrepareAnimatedGifImage() -{ - TextureSet textureSet; - - // load from image file - std::vector pixelDataList; - - if( mImageUrl.IsLocal() ) - { - if( Dali::LoadAnimatedGifFromFile( mImageUrl.GetUrl().c_str() , pixelDataList, mFrameDelayContainer ) ) - { - mImageSize.SetWidth( pixelDataList[0].GetWidth() ); - mImageSize.SetHeight( pixelDataList[0].GetHeight() ); - - Texture texture = Toolkit::ImageAtlas::PackToAtlas( pixelDataList, mTextureRectContainer ); - textureSet = TextureSet::New(); - textureSet.SetTexture( 0, texture ); - } + DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"ResourceReady(ResourceStatus::FAILED)\n"); + ResourceReady( Toolkit::Visual::ResourceStatus::FAILED ); } return textureSet; @@ -505,30 +597,54 @@ void AnimatedImageVisual::FrameReady( TextureSet textureSet ) } else { - mImpl->mRenderer.SetTextures( textureSet ); + if(mImpl->mRenderer) + { + mImpl->mRenderer.SetTextures( textureSet ); + } } } bool AnimatedImageVisual::DisplayNextFrame() { - DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::DisplayNextFrame() start\n"); - - if( mFrameDelayContainer.Count() > 0 ) + if( mActionStatus == DevelAnimatedImageVisual::Action::STOP || mActionStatus == DevelAnimatedImageVisual::Action::PAUSE ) + { + return false; + } + if( mFrameCount > 1 ) { // Wrap the frame index ++mCurrentFrameIndex; - mCurrentFrameIndex %= mFrameDelayContainer.Count(); - mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mTextureRectContainer[mCurrentFrameIndex] ); + if( mLoopCount < 0 || mCurrentLoopIndex < mLoopCount) + { + mCurrentFrameIndex %= mFrameCount; + if( mCurrentFrameIndex == 0 ) + { + ++mCurrentLoopIndex; + } + } + else + { + // This will stop timer + return false; + } + } + DALI_LOG_INFO( gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::DisplayNextFrame(this:%p) FrameCount:%d\n", this, mCurrentFrameIndex); - if( mFrameDelayTimer.GetInterval() != mFrameDelayContainer[mCurrentFrameIndex] ) + if( mFrameDelayContainer.Count() > 0 ) + { + unsigned int delay = mFrameDelayContainer[mCurrentFrameIndex]; + + if( mFrameDelayTimer.GetInterval() != delay ) { - mFrameDelayTimer.SetInterval( mFrameDelayContainer[mCurrentFrameIndex] ); + mFrameDelayTimer.SetInterval( delay ); } } - else if( mImageCache ) + + TextureSet textureSet; + if( mImageCache ) { - TextureSet textureSet = mImageCache->NextFrame(); + textureSet = mImageCache->NextFrame(); if( textureSet ) { SetImageSize( textureSet );