Merge "DALi Version 1.2.22" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-image / animated-image-visual.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "animated-image-visual.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/adaptor-framework/gif-loading.h>
23
24 // INTERNAL INCLUDES
25 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
26 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
27 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
28 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
29 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
30 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
31 #include <dali-toolkit/internal/visuals/image/image-visual.h>
32 #include <dali-toolkit/devel-api/image-loader/image-atlas.h>
33
34 namespace Dali
35 {
36
37 namespace Toolkit
38 {
39
40 namespace Internal
41 {
42
43 AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const std::string& imageUrl, const Property::Map& properties )
44 {
45   AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache );
46   visual->mImageUrl = imageUrl;
47   visual->SetProperties( properties );
48
49   return visual;
50 }
51
52 AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const std::string& imageUrl )
53 {
54   AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache );
55   visual->mImageUrl = imageUrl;
56
57   return visual;
58 }
59
60 AnimatedImageVisual::AnimatedImageVisual( VisualFactoryCache& factoryCache )
61 : Visual::Base( factoryCache ),
62   mFrameDelayTimer(),
63   mImageUrl(),
64   mImageSize(),
65   mCurrentFrameIndex( 0 )
66 {}
67
68 AnimatedImageVisual::~AnimatedImageVisual()
69 {
70 }
71
72 void AnimatedImageVisual::GetNaturalSize( Vector2& naturalSize )
73 {
74   if( mImageSize.GetWidth() == 0 &&  mImageSize.GetHeight() == 0)
75   {
76     mImageSize = Dali::GetGifImageSize( mImageUrl );
77   }
78
79   naturalSize.width = mImageSize.GetWidth();
80   naturalSize.height = mImageSize.GetHeight();
81 }
82
83 void AnimatedImageVisual::DoCreatePropertyMap( Property::Map& map ) const
84 {
85   map.Clear();
86   map.Insert( Toolkit::DevelVisual::Property::TYPE, Toolkit::Visual::IMAGE );
87
88   if( !mImageUrl.empty() )
89   {
90     map.Insert( Toolkit::ImageVisual::Property::URL, mImageUrl );
91   }
92 }
93
94 void AnimatedImageVisual::DoSetProperties( const Property::Map& propertyMap )
95 {
96   // url already passed in from constructor
97 }
98
99 void AnimatedImageVisual::DoSetOnStage( Actor& actor )
100 {
101   Texture texture = PrepareAnimatedImage();
102   if( texture ) // if the image loading is successful
103   {
104     Shader shader = ImageVisual::GetImageShader( mFactoryCache, true, true );
105     Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
106     TextureSet textureSet = TextureSet::New();
107     mImpl->mRenderer = Renderer::New( geometry, shader );
108     mImpl->mRenderer.SetTextures( textureSet );
109     textureSet.SetTexture( 0u, PrepareAnimatedImage() );
110     mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mTextureRectContainer[0] );
111
112     // Register transform properties
113     mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
114
115     mCurrentFrameIndex = 0;
116     if( mFrameDelayContainer.Count() > 1 )
117     {
118       mFrameDelayTimer = Timer::New( mFrameDelayContainer[0] );
119       mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame );
120       mFrameDelayTimer.Start();
121     }
122
123     actor.AddRenderer( mImpl->mRenderer );
124   }
125 }
126
127 void AnimatedImageVisual::DoSetOffStage( Actor& actor )
128 {
129   if( !mImpl->mRenderer )
130   {
131     return;
132   }
133
134   if( mFrameDelayTimer )
135   {
136     mFrameDelayTimer.Stop();
137     mFrameDelayTimer.Reset();
138   }
139
140   mTextureRectContainer.Clear();
141   mFrameDelayContainer.Clear();
142
143   actor.RemoveRenderer( mImpl->mRenderer );
144   mImpl->mRenderer.Reset();
145 }
146
147 void AnimatedImageVisual::OnSetTransform()
148 {
149   if( mImpl->mRenderer )
150   {
151     mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
152   }
153 }
154
155 Texture AnimatedImageVisual::PrepareAnimatedImage()
156 {
157   // load from image file
158   std::vector<Dali::PixelData> pixelDataList;
159   if( Dali::LoadAnimatedGifFromFile( mImageUrl.c_str() , pixelDataList, mFrameDelayContainer ) )
160   {
161     mImageSize.SetWidth( pixelDataList[0].GetWidth() );
162     mImageSize.SetHeight( pixelDataList[0].GetHeight() );
163
164     return Toolkit::ImageAtlas::PackToAtlas( pixelDataList, mTextureRectContainer );
165   }
166
167   return Texture();
168 }
169
170 bool AnimatedImageVisual::DisplayNextFrame()
171 {
172   mCurrentFrameIndex = (mCurrentFrameIndex+1) % mFrameDelayContainer.Count();
173   mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mTextureRectContainer[mCurrentFrameIndex] );
174   if( mFrameDelayTimer.GetInterval() != mFrameDelayContainer[mCurrentFrameIndex] )
175   {
176     mFrameDelayTimer.SetInterval( mFrameDelayContainer[mCurrentFrameIndex] );
177   }
178
179   return true;
180 }
181
182
183 } // namespace Internal
184
185 } // namespace Toolkit
186
187 } // namespace Dali