ad4cd8d26fb79bff628d9d187901d340e424f4c7
[platform/core/uifw/dali-core.git] / dali / internal / event / images / image-impl.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include <dali/internal/event/images/image-impl.h>
19
20 // INTERNAL INCLUDES
21 #include <dali/public-api/common/dali-common.h>
22
23 #include <dali/integration-api/debug.h>
24 #include <dali/internal/event/resources/resource-ticket.h>
25 #include <dali/internal/event/common/thread-local-storage.h>
26 #include <dali/internal/event/resources/resource-client.h>
27 #include <dali/internal/event/images/image-factory.h>
28 #include <dali/internal/event/common/stage-impl.h>
29
30 using namespace Dali::Integration;
31
32 namespace Dali
33 {
34
35 namespace Internal
36 {
37
38 Image::Image( LoadPolicy loadPol, ReleasePolicy releasePol )
39 : mLoadPolicy(loadPol),
40   mReleasePolicy(releasePol),
41   mConnectionCount(0),
42   mImageFactory(ThreadLocalStorage::Get().GetImageFactory())
43 {
44 }
45
46 Image* Image::New()
47 {
48   return new Image;
49 }
50
51 Image* Image::New( const std::string& filename, LoadPolicy loadPol, ReleasePolicy releasePol )
52 {
53   Image* image = Image::New( filename, *static_cast<ImageAttributes*>(NULL), loadPol, releasePol );
54   return image;
55 }
56
57 Image* Image::New( const std::string& filename, const Dali::ImageAttributes& attributes, LoadPolicy loadPol, ReleasePolicy releasePol )
58 {
59   Image* image = new Image( loadPol, releasePol );
60
61   image->mRequest = image->mImageFactory.RegisterRequest( filename, &attributes );
62
63   // Lazily load image data later, only when it is needed to draw something:
64   if( Dali::Image::OnDemand == loadPol )
65   {
66     // Ask for ticket later, only on connect.
67   }
68   else
69   {
70     // Trigger loading of the image over on a resource thread eagerly as soon as it
71     // can be scheduled:
72     image->mTicket = image->mImageFactory.Load( image->mRequest.Get() );
73     image->mTicket->AddObserver( *image );
74   }
75
76   DALI_LOG_SET_OBJECT_STRING( image, filename );
77
78   return image;
79 }
80
81 Image* Image::New( NativeImage& nativeImg, LoadPolicy loadPol, ReleasePolicy releasePol )
82 {
83   Image* image = new Image;
84   ResourceClient &resourceClient = ThreadLocalStorage::Get().GetResourceClient();
85
86   /// @todo check policy and ref with intrusive pointer if needed
87
88   const ResourceTicketPtr& ticket = resourceClient.AddNativeImage( nativeImg );
89   DALI_ASSERT_DEBUG( dynamic_cast<ImageTicket*>( ticket.Get() ) && "Resource ticket not ImageTicket subclass for image resource.\n" );
90   image->mTicket = static_cast<ImageTicket*>(ticket.Get());
91   image->mTicket->AddObserver( *image );
92
93   return image;
94 }
95
96 Image::~Image()
97 {
98   if( mTicket )
99   {
100     mTicket->RemoveObserver( *this );
101     if( Stage::IsInstalled() )
102     {
103       mImageFactory.ReleaseTicket( mTicket.Get() );
104     }
105   }
106 }
107
108 bool Image::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
109 {
110   bool connected( true );
111   DALI_ASSERT_DEBUG( dynamic_cast<Image*>( object ) && "Resource ticket not ImageTicket subclass for image resource.\n" );
112   Image* image = static_cast<Image*>(object);
113
114   if( Dali::Image::SIGNAL_IMAGE_LOADING_FINISHED == signalName )
115   {
116     image->LoadingFinishedSignal().Connect( tracker, functor );
117   }
118   else if(Dali::Image::SIGNAL_IMAGE_UPLOADED == signalName)
119   {
120     image->UploadedSignal().Connect( tracker, functor );
121   }
122   else
123   {
124     // signalName does not match any signal
125     connected = false;
126   }
127
128   return connected;
129 }
130
131 ResourceId Image::GetResourceId() const
132 {
133   ResourceId ret = mTicket ? mTicket->GetId() : 0;
134
135   return ret;
136 }
137
138 const Dali::ImageAttributes& Image::GetAttributes() const
139 {
140   if( mTicket )
141   {
142     return mImageFactory.GetActualAttributes( mTicket->GetId() );
143   }
144   else
145   {
146     return mImageFactory.GetRequestAttributes( mRequest.Get() );
147   }
148 }
149
150 const std::string& Image::GetFilename() const
151 {
152   return mImageFactory.GetRequestPath( mRequest.Get() );
153 }
154
155 void Image::Reload()
156 {
157   if ( mRequest )
158   {
159     ResourceTicketPtr ticket = mImageFactory.Reload( mRequest.Get() );
160     SetTicket( ticket.Get() );
161   }
162 }
163
164 void Image::ResourceLoadingFailed(const ResourceTicket& ticket)
165 {
166   mLoadingFinishedV2.Emit( Dali::Image( this ) );
167 }
168
169 void Image::ResourceLoadingSucceeded(const ResourceTicket& ticket)
170 {
171   mLoadingFinishedV2.Emit( Dali::Image( this ) );
172 }
173
174 void Image::ResourceUploaded(const ResourceTicket& ticket)
175 {
176   mUploadedV2.Emit( Dali::Image( this ) );
177 }
178
179 void Image::ResourceSavingSucceeded( const ResourceTicket& ticket )
180 {
181   // do nothing
182 }
183
184 void Image::ResourceSavingFailed( const ResourceTicket& ticket )
185 {
186   // do nothing
187 }
188
189 unsigned int Image::GetWidth() const
190 {
191   if( mTicket )
192   {
193     const ImageAttributes& attr = mImageFactory.GetActualAttributes( mTicket->GetId() );
194     return attr.GetWidth();
195   }
196   else
197   {
198     const ImageAttributes& attr = mImageFactory.GetRequestAttributes( mRequest.Get() );
199     return attr.GetWidth();
200   }
201 }
202
203 unsigned int Image::GetHeight() const
204 {
205   if( mTicket )
206   {
207     const ImageAttributes& attr = mImageFactory.GetActualAttributes( mTicket->GetId() );
208     return attr.GetHeight();
209   }
210   else
211   {
212     const ImageAttributes& attr = mImageFactory.GetRequestAttributes( mRequest.Get() );
213     return attr.GetHeight();
214   }
215 }
216
217 void Image::Connect()
218 {
219   ++mConnectionCount;
220
221   if( mConnectionCount == 1 )
222   {
223     // ticket was thrown away when related actors went offstage or image loading on demand
224     if( !mTicket )
225     {
226       ResourceTicketPtr newTicket = mImageFactory.Load( mRequest.Get() );
227       SetTicket( newTicket.Get() );
228     }
229   }
230 }
231
232 void Image::Disconnect()
233 {
234   if( !mTicket )
235   {
236     return;
237   }
238
239   DALI_ASSERT_DEBUG( mConnectionCount > 0 );
240   --mConnectionCount;
241   if( mConnectionCount == 0 && mReleasePolicy == Dali::Image::Unused )
242   {
243     // release image memory when it's not visible anymore (decrease ref. count of texture)
244     SetTicket( NULL );
245   }
246 }
247
248 void Image::SetTicket( ResourceTicket* ticket )
249 {
250   if( ticket == mTicket.Get() )
251   {
252     return;
253   }
254
255   if( mTicket )
256   {
257     mTicket->RemoveObserver( *this );
258     mImageFactory.ReleaseTicket( mTicket.Get() );
259   }
260
261   if( ticket )
262   {
263     mTicket.Reset( ticket );
264     mTicket->AddObserver( *this );
265   }
266   else
267   {
268     mTicket.Reset();
269   }
270 }
271
272 } // namespace Internal
273
274 } // namespace Dali