Emscripten workarounds and llvm syntax fixes
[platform/core/uifw/dali-core.git] / dali / internal / event / resources / resource-client.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 // INTERNAL INCLUDES
18 #include <dali/internal/event/resources/resource-client.h>
19 #include <dali/public-api/common/map-wrapper.h>
20
21 #include <dali/integration-api/glyph-set.h>
22 #include <dali/integration-api/resource-request.h>
23 #include <dali/integration-api/debug.h>
24
25 #include <dali/internal/event/common/stage-impl.h>
26 #include <dali/internal/event/text/resource/glyph-load-observer.h>
27 #include <dali/internal/event/images/image-impl.h>
28 #include <dali/internal/update/resources/resource-manager.h>
29 #include <dali/internal/update/manager/update-manager.h>
30
31
32 namespace Dali
33 {
34 namespace Internal
35 {
36 using namespace Dali::Integration;
37
38 typedef std::map<ResourceId, ResourceTicket*>        TicketContainer;
39 typedef TicketContainer::iterator                    TicketContainerIter;
40 typedef TicketContainer::size_type                   TicketContainerSize;
41 typedef std::pair<ResourceId, ResourceTicket*>       TicketPair;
42
43 typedef std::map<ResourceId, Bitmap*>                BitmapCache;
44 typedef BitmapCache::iterator                        BitmapCacheIter;
45
46 struct ResourceClient::Impl
47 {
48   Impl()
49   : mNextId(0),
50     mGlyphLoadObserver( NULL)
51   {
52   }
53
54   ResourceId       mNextId;
55   TicketContainer  mTickets;
56   BitmapCache      mBitmaps;
57   GlyphLoadObserver* mGlyphLoadObserver;
58 };
59
60 ResourceClient::ResourceClient( ResourceManager& resourceManager,
61                                 SceneGraph::UpdateManager& updateManager )
62 : mResourceManager(resourceManager),
63   mUpdateManager(updateManager)
64 {
65   mImpl = new ResourceClient::Impl();
66   mResourceManager.SetClient(*this);
67 }
68
69 ResourceClient::~ResourceClient()
70 {
71   // Guard to allow handle destruction after Core has been destroyed
72   if ( Stage::IsInstalled() )
73   {
74     for (TicketContainerIter iter = mImpl->mTickets.begin(); iter != mImpl->mTickets.end(); ++iter)
75     {
76       (*iter).second->StopLifetimeObservation();
77     }
78   }
79   delete mImpl;
80 }
81
82 ResourceTicketPtr ResourceClient::RequestResource(
83   const ResourceType& type,
84   const std::string& path,
85   LoadResourcePriority priority )
86 {
87   ResourceTicketPtr newTicket;
88   ResourceTypePath typePath(type, path);
89   ResourceId newId = 0;
90
91   // Create the ticket first
92   // NOTE: pre-increment, otherwise we get 0 for first one.
93   newId = ++(mImpl->mNextId);
94
95   switch (type.id)
96   {
97     case ResourceBitmap:
98     {
99       const BitmapResourceType& bitmapResource = static_cast <const BitmapResourceType&> (type);
100       // image tickets will cache the requested parameters, which are updated on successful loading
101       ImageTicket* imageTicket = new ImageTicket(*this, newId, typePath);
102       imageTicket->mAttributes = bitmapResource.imageAttributes;
103       newTicket = imageTicket;
104       break;
105     }
106
107     case ResourceNativeImage:
108     {
109       const NativeImageResourceType& nativeResource = static_cast <const NativeImageResourceType&> (type);
110       // image tickets will cache the requested parameters, which are updated on successful loading
111       ImageTicket* imageTicket = new ImageTicket(*this, newId, typePath);
112       imageTicket->mAttributes = nativeResource.imageAttributes;
113       newTicket = imageTicket;
114       break;
115     }
116     case ResourceModel:       // FALLTHROUGH
117     case ResourceTargetImage:
118     case ResourceShader:
119     case ResourceMesh:
120     case ResourceText:
121     {
122       newTicket = new ResourceTicket(*this, newId, typePath);
123       break;
124     }
125   }
126
127   mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
128
129   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: RequestResource(path:%s type.id:%d) newId:%u\n", path.c_str(), type.id, newId);
130
131   RequestLoadResourceMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, newId, typePath, priority );
132   return newTicket;
133 }
134
135 ResourceTicketPtr ResourceClient::DecodeResource(
136   const ResourceType& type,
137   RequestBufferPtr buffer,
138   LoadResourcePriority priority )
139 {
140   DALI_ASSERT_DEBUG( type.id == ResourceBitmap && "Only bitmap resources are currently decoded from memory buffers. It should be easy to expand to other resource types though. The public API function at the front and the resource thread at the back end are all that should need to be changed. The code in the middle should be agnostic to the the resource type it is conveying.\n" );
141   DALI_ASSERT_DEBUG( buffer.Get() && "Null resource buffer passed for decoding." );
142   ResourceTicketPtr newTicket;
143   if( buffer.Get() ) //< Check to avoid SEGV on a null pointer.
144   {
145     ResourceTypePath typePath( type, "" );
146     ResourceId newId = 0;
147
148     // Create the correct ticket type for the resource:
149     switch (type.id)
150     {
151       case ResourceBitmap:
152       {
153         // NOTE: pre-increment, otherwise we get 0 for first one.
154         newId = ++(mImpl->mNextId);
155         const BitmapResourceType& bitmapResource = static_cast <const BitmapResourceType&> ( type );
156         // Image tickets will cache the requested parameters, which are updated on successful loading
157         ImageTicket* imageTicket = new ImageTicket( *this, newId, typePath );
158         imageTicket->mAttributes = bitmapResource.imageAttributes;
159         newTicket = imageTicket;
160         break;
161       }
162
163       // FALLTHROUGH:
164       case ResourceNativeImage:
165       case ResourceModel:
166       case ResourceTargetImage:
167       case ResourceShader:
168       case ResourceMesh:
169       case ResourceText:
170       {
171         DALI_LOG_ERROR( "Unsupported resource type passed for decoding from a memory buffer." );
172       }
173     }
174
175     if( newTicket )
176     {
177       mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
178       DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: DecodeResource( type.id:%d ) newId:%u\n", type.id, newId);
179
180       RequestDecodeResourceMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, newId, typePath, buffer, priority );
181     }
182   }
183   return newTicket;
184 }
185
186 ResourceTicketPtr ResourceClient::LoadShader( ShaderResourceType& type,
187                                               const std::string& path )
188 {
189   ResourceTicketPtr newTicket;
190
191   const ResourceId newId = ++(mImpl->mNextId);
192
193   ResourceTypePath typePath(type, path);
194   newTicket = new ResourceTicket(*this, newId, typePath);
195
196   mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
197
198   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: LoadShader(path:%s) newId:%u\n", path.c_str(), newId);
199
200   RequestLoadShaderMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, newId, typePath );
201   return newTicket;
202 }
203
204 bool ResourceClient::ReloadResource( ResourceId id, LoadResourcePriority priority )
205 {
206   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: ReloadResource(Id: %u)\n", id);
207
208   bool resourceExists = false;
209   TicketContainerIter ticketIter;
210   ticketIter = mImpl->mTickets.find(id);
211
212   if(ticketIter != mImpl->mTickets.end())
213   {
214     resourceExists = true;
215     // The ticket is already being observed
216     ResourceTicket* ticket = ticketIter->second;
217     DALI_ASSERT_DEBUG(ticket && "Null ticket for tracked resource request." );
218     const ResourceTypePath * const typePathPtr = &ticket->GetTypePath();
219     DALI_ASSERT_DEBUG( typePathPtr );
220     RequestReloadResourceMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, id, *typePathPtr, priority );
221   }
222   else
223   {
224     DALI_LOG_ERROR ("Resource %d does not exist\n", id);
225   }
226   return resourceExists;
227 }
228
229 void ResourceClient::SaveResource( ResourceTicketPtr ticket, const std::string& url )
230 {
231   DALI_ASSERT_DEBUG( ticket );
232
233   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: SaveResource(Id: %u, path:%s)\n", ticket->GetId(), url.c_str());
234
235   const ResourceTypePath * const typePathPtr = &ticket->GetTypePath();
236   if( typePathPtr )
237   {
238     if( 0 != url.length() )
239     {
240       ResourceTypePath typePath( *(typePathPtr->type), url );
241       RequestSaveResourceMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, ticket->GetId(), typePath );
242     }
243     else
244     {
245       ResourceTypePath typePath( *typePathPtr );
246       RequestSaveResourceMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, ticket->GetId(), typePath );
247     }
248   }
249 }
250
251 ResourceTicketPtr ResourceClient::RequestResourceTicket( ResourceId id )
252 {
253   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: RequestResourceTicket(Id: %u)\n", id);
254
255   ResourceTicketPtr ticket;
256
257   TicketContainerIter ticketIter = mImpl->mTickets.find( id );
258
259   if ( mImpl->mTickets.end() != ticketIter )
260   {
261     ticket = ticketIter->second;
262   }
263
264   return ticket;
265 }
266
267 ImageTicketPtr ResourceClient::AllocateBitmapImage ( unsigned int width,
268                                                      unsigned int height,
269                                                      unsigned int bufferWidth,
270                                                      unsigned int bufferHeight,
271                                                      Pixel::Format pixelformat )
272 {
273   Bitmap * const bitmap = Bitmap::New(Bitmap::BITMAP_2D_PACKED_PIXELS, true); ///< Not exception safe.
274   Bitmap::PackedPixelsProfile * const packedBitmap = bitmap->GetPackedPixelsProfile();
275   DALI_ASSERT_DEBUG(packedBitmap);
276
277   packedBitmap->ReserveBuffer(pixelformat, width, height, bufferWidth, bufferHeight);
278   DALI_ASSERT_DEBUG(bitmap->GetBuffer() != 0);
279   DALI_ASSERT_DEBUG(bitmap->GetBufferSize() >= width * height);
280
281   ImageTicketPtr ticket = AddBitmapImage(bitmap);
282
283   DALI_ASSERT_DEBUG(bitmap->GetBuffer() != 0);
284   DALI_ASSERT_DEBUG(bitmap->GetBufferSize() >= width * height);
285   return ticket;
286 }
287
288 ImageTicketPtr ResourceClient::AddBitmapImage(Bitmap* bitmap)
289 {
290   DALI_ASSERT_DEBUG( bitmap != NULL );
291
292   ImageTicketPtr newTicket;
293
294   const ResourceId newId = ++(mImpl->mNextId);
295
296   Dali::ImageAttributes imageAttributes = Dali::ImageAttributes::New(bitmap->GetImageWidth(), bitmap->GetImageHeight(), bitmap->GetPixelFormat());
297   BitmapResourceType bitmapResourceType(imageAttributes); // construct first as no copy ctor (needed to bind ref to object)
298   ResourceTypePath typePath(bitmapResourceType, "");
299   newTicket = new ImageTicket(*this, newId, typePath);
300   newTicket->mAttributes = imageAttributes;
301   newTicket->LoadingSucceeded();
302
303   mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
304
305   // Store bitmap for immediate access.
306   mImpl->mBitmaps[newId] = bitmap;
307
308   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddBitmapImage() New id = %u\n", newId);
309   RequestAddBitmapImageMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, newId, bitmap );
310
311   return newTicket;
312 }
313
314 ResourceTicketPtr ResourceClient::AddNativeImage ( NativeImage& resourceData )
315 {
316   ImageTicketPtr newTicket;
317
318   const ResourceId newId = ++(mImpl->mNextId);
319   NativeImageResourceType nativeImageResourceType; // construct first as no copy ctor (needed to bind ref to object)
320   ResourceTypePath typePath(nativeImageResourceType, "");
321   newTicket = new ImageTicket(*this, newId, typePath);
322   newTicket->mAttributes = ImageAttributes::New(resourceData.GetWidth(),
323                                                 resourceData.GetHeight(),
324                                                 resourceData.GetPixelFormat());
325   newTicket->LoadingSucceeded();
326
327   mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
328
329   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddNativeImage() New id = %u\n", newId);
330
331   RequestAddNativeImageMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, newId, &resourceData );
332
333   return newTicket;
334 }
335
336 ImageTicketPtr ResourceClient::AddFrameBufferImage ( unsigned int width, unsigned int height, Pixel::Format pixelFormat )
337 {
338   ImageTicketPtr newTicket;
339
340   const ResourceId newId = ++(mImpl->mNextId);
341
342   Dali::ImageAttributes imageAttributes = Dali::ImageAttributes::New(width, height, pixelFormat );
343   RenderTargetResourceType renderTargetResourceType(imageAttributes) ; // construct first as no copy ctor (needed to bind ref to object)
344   ResourceTypePath typePath(renderTargetResourceType, "");
345   newTicket = new ImageTicket(*this, newId, typePath);
346   newTicket->mAttributes = imageAttributes;
347   newTicket->LoadingSucceeded();
348
349   mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
350
351   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddFrameBufferImage() New id = %u\n", newId);
352   RequestAddFrameBufferImageMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, newId, width, height, pixelFormat );
353
354   return newTicket;
355 }
356
357 ImageTicketPtr ResourceClient::AddFrameBufferImage ( NativeImage& nativeImage )
358 {
359   ImageTicketPtr newTicket;
360
361   const ResourceId newId = ++(mImpl->mNextId);
362
363   Dali::ImageAttributes imageAttributes = Dali::ImageAttributes::New(nativeImage.GetWidth(), nativeImage.GetHeight(), nativeImage.GetPixelFormat() );
364   RenderTargetResourceType renderTargetResourceType(imageAttributes); // construct first as no copy ctor (needed to bind ref to object)
365   ResourceTypePath typePath(renderTargetResourceType, "");
366   newTicket = new ImageTicket(*this, newId, typePath);
367   newTicket->mAttributes = imageAttributes;
368   newTicket->LoadingSucceeded();
369
370   mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
371
372   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddFrameBufferImage() New id = %u\n", newId);
373   RequestAddFrameBufferImageMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, newId, &nativeImage );
374
375   return newTicket;
376 }
377
378
379 ResourceTicketPtr ResourceClient::AllocateTexture( unsigned int width,
380                                                    unsigned int height,
381                                                    Pixel::Format pixelformat )
382 {
383   ImageTicketPtr newTicket;
384   const ResourceId newId = ++(mImpl->mNextId);
385
386   Dali::ImageAttributes imageAttributes = Dali::ImageAttributes::New( width, height, pixelformat);
387   BitmapResourceType bitmapResourceType(imageAttributes); // construct first as no copy ctor (needed to bind ref to object)
388   ResourceTypePath typePath(bitmapResourceType, "");
389   newTicket = new ImageTicket(*this, newId, typePath);
390
391   mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
392   newTicket->mAttributes = imageAttributes;
393   newTicket->LoadingSucceeded();
394
395   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AllocateTexture() New id = %u\n", newId);
396
397   RequestAllocateTextureMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, newId, width, height, pixelformat );
398
399   return newTicket;
400 }
401
402 void ResourceClient::UpdateTexture(  ResourceId id,
403                                      BitmapUploadArray uploadArray )
404 {
405   RequestUpdateTextureMessage(  mUpdateManager.GetEventToUpdate(), mResourceManager, id, uploadArray );
406 }
407
408 ResourceTicketPtr ResourceClient::AllocateMesh( OwnerPointer<MeshData>& meshData )
409 {
410   ResourceTicketPtr newTicket;
411   const ResourceId newId = ++(mImpl->mNextId);
412   MeshResourceType meshResourceType; // construct first as no copy ctor (needed to bind ref to object)
413   ResourceTypePath typePath(meshResourceType, "");
414   newTicket = new ResourceTicket(*this, newId, typePath);
415   mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
416
417   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AllocateMesh() New id = %u\n", newId);
418   RequestAllocateMeshMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, newId, meshData );
419
420   return newTicket;
421 }
422
423 void ResourceClient::UpdateBitmapArea( ResourceTicketPtr ticket, RectArea& updateArea )
424 {
425   DALI_ASSERT_DEBUG( ticket );
426
427   RequestUpdateBitmapAreaMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, ticket->GetId(), updateArea );
428 }
429
430 void ResourceClient::UpdateMesh( ResourceTicketPtr ticket, const Dali::MeshData& meshData )
431 {
432   DALI_ASSERT_DEBUG( ticket );
433
434   RequestUpdateMeshMessage( mUpdateManager.GetEventToUpdate(),
435                             mResourceManager,
436                             ticket->GetId(),
437                             meshData );
438 }
439
440 Bitmap* ResourceClient::GetBitmap(ResourceTicketPtr ticket)
441 {
442   DALI_ASSERT_DEBUG( ticket );
443
444   Bitmap* bitmap = NULL;
445   BitmapCacheIter iter = mImpl->mBitmaps.find(ticket->GetId());
446
447   if( iter != mImpl->mBitmaps.end() )
448   {
449     bitmap = iter->second;
450   }
451   return bitmap;
452 }
453
454 void ResourceClient::SetGlyphLoadObserver( GlyphLoadObserver* glyphLoadedInterface )
455 {
456   mImpl->mGlyphLoadObserver = glyphLoadedInterface;
457 }
458
459 void ResourceClient::UpdateAtlasStatus( ResourceId id, ResourceId atlasId, Integration::LoadStatus loadStatus )
460 {
461   RequestAtlasUpdateMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, id, atlasId, loadStatus );
462 }
463
464 /********************************************************************************
465  ********************   ResourceTicketLifetimeObserver methods   ****************
466  ********************************************************************************/
467
468 void ResourceClient::ResourceTicketDiscarded(const ResourceTicket& ticket)
469 {
470   const ResourceId deadId = ticket.GetId();
471   const ResourceTypePath& typePath = ticket.GetTypePath();
472
473   // Ensure associated event owned resources are also removed
474   mImpl->mBitmaps.erase(ticket.GetId());
475
476   // The ticket object is dead, remove from tickets container
477   TicketContainerSize erased = mImpl->mTickets.erase(deadId);
478   DALI_ASSERT_DEBUG(erased != 0);
479   (void)erased; // Avoid "unused variable erased" in release builds
480
481   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: ResourceTicketDiscarded() deadId = %u\n", deadId);
482   RequestDiscardResourceMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, deadId, typePath.type->id );
483 }
484
485 /********************************************************************************
486  ***********************   Notifications from ResourceManager  ******************
487  ********************************************************************************/
488
489 void ResourceClient::NotifyUploaded( ResourceId id )
490 {
491   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyUpdated(id:%u)\n", id);
492
493   TicketContainerIter ticketIter = mImpl->mTickets.find(id);
494   if(ticketIter != mImpl->mTickets.end())
495   {
496     ResourceTicket* ticket = ticketIter->second;
497     ticket->Uploaded();
498   }
499 }
500
501 void ResourceClient::NotifySaveRequested( ResourceId id )
502 {
503   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifySaveRequested(id:%u)\n", id);
504
505   TicketContainerIter ticketIter = mImpl->mTickets.find(id);
506   if(ticketIter != mImpl->mTickets.end())
507   {
508     ResourceTicket* ticket = ticketIter->second;
509     SaveResource( ticket, "" );
510   }
511 }
512
513
514 void ResourceClient::NotifyLoading( ResourceId id )
515 {
516   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyLoading(id:%u)\n", id);
517
518   TicketContainerIter ticketIter = mImpl->mTickets.find(id);
519   if(ticketIter != mImpl->mTickets.end())
520   {
521     ResourceTicket* ticket = ticketIter->second;
522     ticket->Loading();
523   }
524 }
525
526 void ResourceClient::NotifyLoadingSucceeded( ResourceId id )
527 {
528   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyLoadingSucceeded(id:%u)\n", id);
529
530   TicketContainerIter ticketIter = mImpl->mTickets.find(id);
531   if(ticketIter != mImpl->mTickets.end())
532   {
533     ResourceTicket* ticket = ticketIter->second;
534     ticket->LoadingSucceeded();
535   }
536 }
537
538 void ResourceClient::NotifyLoadingFailed( ResourceId id )
539 {
540   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyLoadingFailed(id:%u)\n", id);
541
542   TicketContainerIter ticketIter = mImpl->mTickets.find(id);
543   if(ticketIter != mImpl->mTickets.end())
544   {
545     ResourceTicket* ticket = ticketIter->second;
546     ticket->LoadingFailed();
547   }
548 }
549
550 void ResourceClient::NotifySavingSucceeded( ResourceId id )
551 {
552   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifySavingSucceeded(id:%u)\n", id);
553
554   TicketContainerIter ticketIter = mImpl->mTickets.find(id);
555   if(ticketIter != mImpl->mTickets.end())
556   {
557     ResourceTicket* ticket = ticketIter->second;
558     ticket->SavingSucceeded();
559   }
560 }
561
562 void ResourceClient::NotifySavingFailed( ResourceId id )
563 {
564   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifySavingFailed(id:%u)\n", id);
565
566   TicketContainerIter ticketIter = mImpl->mTickets.find(id);
567   if(ticketIter != mImpl->mTickets.end())
568   {
569     ResourceTicket* ticket = ticketIter->second;
570     ticket->SavingFailed();
571   }
572 }
573
574 void ResourceClient::NotifyGlyphSetLoaded( ResourceId id, const GlyphSet& glyphSet, LoadStatus loadStatus )
575 {
576   if( mImpl->mGlyphLoadObserver == NULL)
577   {
578     // should not happen.
579     DALI_ASSERT_DEBUG( !"GlyphLoadObserver == NULL ");
580     return;
581   }
582
583   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyGlyphSetLoaded(hash:%u)\n", glyphSet.mFontHash);
584
585   mImpl->mGlyphLoadObserver->GlyphsLoaded( id, glyphSet, loadStatus );
586 }
587
588 void ResourceClient::UpdateImageTicket( ResourceId id, const Dali::ImageAttributes& imageAttributes ) ///!< Issue #AHC01
589 {
590   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: UpdateImageTicket(id:%u)\n", id);
591
592   TicketContainerIter ticketIter = mImpl->mTickets.find(id);
593   if(ticketIter != mImpl->mTickets.end())
594   {
595     ResourceTicket* ticket = ticketIter->second;
596     ImageTicketPtr imageTicket = dynamic_cast<ImageTicket*>(ticket);
597     if(imageTicket)
598     {
599       imageTicket->mAttributes = imageAttributes;
600     }
601   }
602 }
603
604 } // Internal
605
606 } // Dali