[Tizen] Use broken image when animated image loading is failed
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / common / gif-loading.cpp
index a6793f2..1b195b9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
 #include <dali/internal/imaging/common/gif-loading.h>
 
 // EXTERNAL INCLUDES
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <fcntl.h>
-#include <unistd.h>
 #include <gif_lib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
 #include <cstring>
+#include <memory>
+
+#include <dali/devel-api/threading/mutex.h>
 #include <dali/integration-api/debug.h>
-#include <dali/public-api/images/pixel-data.h>
 #include <dali/internal/imaging/common/file-download.h>
 #include <dali/internal/system/common/file-reader.h>
+#include <dali/public-api/images/pixel-data.h>
 
-#define IMG_TOO_BIG( w, h )                                                        \
-  ( ( static_cast<unsigned long long>(w) * static_cast<unsigned long long>(h) ) >= \
-    ( (1ULL << (29 * (sizeof(void *) / 4))) - 2048) )
+#define IMG_TOO_BIG(w, h)                                                       \
+  ((static_cast<unsigned long long>(w) * static_cast<unsigned long long>(h)) >= \
+   ((1ULL << (29 * (sizeof(void*) / 4))) - 2048))
 
-#define LOADERR( x )                              \
-  do {                                            \
-    DALI_LOG_ERROR( x );                          \
-    goto on_error;                                \
-  } while ( 0 )
+#define LOADERR(x)     \
+  do                   \
+  {                    \
+    DALI_LOG_ERROR(x); \
+    goto on_error;     \
+  } while(0)
 
 namespace Dali
 {
-
 namespace Internal
 {
-
 namespace Adaptor
 {
-
 namespace
 {
 #if defined(DEBUG_ENABLED)
-Debug::Filter *gGifLoadingLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_GIF_LOADING" );
+Debug::Filter* gGifLoadingLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_GIF_LOADING");
 #endif
 
-const int IMG_MAX_SIZE = 65000;
-constexpr size_t MAXIMUM_DOWNLOAD_IMAGE_SIZE  = 50 * 1024 * 1024;
+const int        IMG_MAX_SIZE                = 65000;
+constexpr size_t MAXIMUM_DOWNLOAD_IMAGE_SIZE = 50 * 1024 * 1024;
 
 #if GIFLIB_MAJOR < 5
-const int DISPOSE_BACKGROUND = 2;       /* Set area too background color */
-const int DISPOSE_PREVIOUS = 3;         /* Restore to previous content */
+const int DISPOSE_BACKGROUND = 2; /* Set area too background color */
+const int DISPOSE_PREVIOUS   = 3; /* Restore to previous content */
 #endif
 
 struct FrameInfo
 {
   FrameInfo()
-  : x( 0 ),
-    y( 0 ),
-    w( 0 ),
-    h( 0 ),
-    delay( 0 ),
-    transparent( -1 ),
-    dispose( DISPOSE_BACKGROUND ),
-    interlace( 0 )
+  : x(0),
+    y(0),
+    w(0),
+    h(0),
+    delay(0),
+    transparent(-1),
+    dispose(DISPOSE_BACKGROUND),
+    interlace(0)
   {
   }
 
-  int x, y, w, h;
-  unsigned short delay; // delay time in 1/100ths of a sec
-  short transparent : 10; // -1 == not, anything else == index
-  short dispose : 6; // 0, 1, 2, 3 (others invalid)
-  short interlace : 1; // interlaced or not
+  int            x, y, w, h;
+  unsigned short delay;            // delay time in 1/100ths of a sec
+  short          transparent : 10; // -1 == not, anything else == index
+  short          dispose : 6;      // 0, 1, 2, 3 (others invalid)
+  short          interlace : 1;    // interlaced or not
 };
 
 struct ImageFrame
 {
   ImageFrame()
-  : index( 0 ),
-    data( nullptr ),
+  : index(0),
+    data(nullptr),
     info(),
-    loaded( false )
+    loaded(false)
   {
   }
 
   ~ImageFrame()
   {
+    if(data != nullptr)
+    {
+      // De-allocate memory of the frame data.
+      delete[] data;
+      data = nullptr;
+    }
   }
 
   int       index;
-  uint32_t  *data;     /* frame decoding data */
-  FrameInfo  info;     /* special image type info */
-  bool loaded : 1;
+  uint32_t* data; /* frame decoding data */
+  FrameInfo info; /* special image type info */
+  bool      loaded : 1;
 };
 
 struct GifAnimationData
 {
   GifAnimationData()
-  : frames( ),
-    frameCount( 0 ),
-    loopCount( 0 ),
-    currentFrame( 0 ),
-    animated( false )
+  : frames(),
+    frameCount(0),
+    loopCount(0),
+    currentFrame(0),
+    animated(false)
   {
   }
 
   std::vector<ImageFrame> frames;
-  int frameCount;
-  int loopCount;
-  int currentFrame;
-  bool animated;
+  int                     frameCount;
+  int                     loopCount;
+  int                     currentFrame;
+  bool                    animated;
 };
 
+// Forward declaration
+struct GifAccessor;
+
 struct LoaderInfo
 {
   LoaderInfo()
-  : gif( nullptr ) ,
-    imageNumber ( 0 )
   {
   }
 
   struct FileData
   {
     FileData()
-    : fileName( nullptr ),
-      globalMap ( nullptr ),
-      length( 0 ),
-      isLocalResource( true )
+    : fileName(nullptr),
+      globalMap(nullptr),
+      length(0),
+      isLocalResource(true)
+    {
+    }
+
+    ~FileData()
     {
+      if(globalMap)
+      {
+        free(globalMap);
+        globalMap = nullptr;
+      }
     }
 
-    const char *fileName;  /**< The absolute path of the file. */
-    unsigned char *globalMap ;      /**< A pointer to the entire contents of the file that have been mapped with mmap(2). */
-    long long length;  /**< The length of the file in bytes. */
-    bool isLocalResource; /**< The flag whether the file is a local resource */
+    bool LoadFile();
+
+  private:
+    bool LoadLocalFile();
+    bool LoadRemoteFile();
+
+  public:
+    const char*    fileName;        /**< The absolute path of the file. */
+    unsigned char* globalMap;       /**< A pointer to the entire contents of the file */
+    long long      length;          /**< The length of the file in bytes. */
+    bool           isLocalResource; /**< The flag whether the file is a local resource */
   };
 
   struct FileInfo
   {
     FileInfo()
-    : map( nullptr ),
-      position( 0 ),
-      length( 0 )
+    : map(nullptr),
+      position(0),
+      length(0)
     {
     }
 
-    unsigned char *map;
-    int position, length; // yes - gif uses ints for file sizes.
+    unsigned charmap;
+    int            position, length; // yes - gif uses ints for file sizes.
   };
 
-  FileData fileData;
-  GifAnimationData animated;
-  GifFileType *gif;
-  int imageNumber;
-  FileInfo fileInfo;
+  FileData                     fileData;
+  GifAnimationData             animated;
+  std::unique_ptr<GifAccessor> gifAccessor{nullptr};
+  int                          imageNumber{0};
+  FileInfo                     fileInfo;
 };
 
 struct ImageProperties
 {
-  ImageProperties()
-  : w( 0 ),
-    h( 0 ),
-    alpha( 0 )
+  unsigned int w{0};
+  unsigned int h{0};
+  bool         alpha{0};
+};
+
+/**
+ * Class to access gif open/close using riaa
+ */
+struct GifAccessor
+{
+  /**
+   * Constructor
+   * @param[in,out] fileInfo Contains ptr to memory, and is updated by DGifOpen
+   */
+  GifAccessor(LoaderInfo::FileInfo& fileInfo)
+  {
+// actually ask libgif to open the file
+#if GIFLIB_MAJOR >= 5
+    gif = DGifOpen(&fileInfo, FileRead, NULL);
+#else
+    gif = DGifOpen(&fileInfo, FileRead);
+#endif
+
+    if(!gif)
+    {
+      DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+    }
+  }
+
+  ~GifAccessor()
+  {
+    if(gif)
+    {
+#if(GIFLIB_MAJOR > 5) || ((GIFLIB_MAJOR == 5) && (GIFLIB_MINOR >= 1))
+      DGifCloseFile(gif, NULL);
+#else
+      DGifCloseFile(gif);
+#endif
+    }
+  }
+
+  /**
+   * @brief Copy data from gif file into buffer.
+   *
+   * @param[in] gifFileType A pointer pointing to GIF File Type
+   * @param[out] buffer A pointer to buffer containing GIF raw data
+   * @param[in] len The length in bytes to be copied
+   * @return The data length of the image in bytes
+   */
+  static int FileRead(GifFileType* gifFileType, GifByteType* buffer, int length)
   {
+    LoaderInfo::FileInfo* fi = reinterpret_cast<LoaderInfo::FileInfo*>(gifFileType->UserData);
+
+    if(fi->position >= fi->length)
+    {
+      return 0; // if at or past end - no
+    }
+    if((fi->position + length) >= fi->length)
+    {
+      length = fi->length - fi->position;
+    }
+    memcpy(buffer, fi->map + fi->position, length);
+    fi->position += length;
+    return length;
   }
 
-  unsigned int w;
-  unsigned int h;
-  bool alpha;
+  GifFileType* gif = nullptr;
 };
 
+bool LoaderInfo::FileData::LoadFile()
+{
+  bool success = false;
+  if(isLocalResource)
+  {
+    success = LoadLocalFile();
+  }
+  else
+  {
+    success = LoadRemoteFile();
+  }
+  return success;
+}
+
+bool LoaderInfo::FileData::LoadLocalFile()
+{
+  Internal::Platform::FileReader fileReader(fileName);
+  FILE*                          fp = fileReader.GetFile();
+  if(fp == NULL)
+  {
+    return false;
+  }
+
+  if(fseek(fp, 0, SEEK_END) <= -1)
+  {
+    return false;
+  }
+
+  length = ftell(fp);
+  if(length <= -1)
+  {
+    return false;
+  }
+
+  if((!fseek(fp, 0, SEEK_SET)))
+  {
+    globalMap = reinterpret_cast<GifByteType*>(malloc(sizeof(GifByteType) * length));
+    length    = fread(globalMap, sizeof(GifByteType), length, fp);
+  }
+  else
+  {
+    return false;
+  }
+  return true;
+}
+
+bool LoaderInfo::FileData::LoadRemoteFile()
+{
+  // remote file
+  bool                  succeeded = false;
+  Dali::Vector<uint8_t> dataBuffer;
+  size_t                dataSize;
+
+  succeeded = TizenPlatform::Network::DownloadRemoteFileIntoMemory(fileName, dataBuffer, dataSize, MAXIMUM_DOWNLOAD_IMAGE_SIZE);
+  if(succeeded)
+  {
+    size_t blobSize = dataBuffer.Size();
+    if(blobSize > 0U)
+    {
+      // Open a file handle on the memory buffer:
+      Dali::Internal::Platform::FileReader fileReader(dataBuffer, blobSize);
+      FILE* const                          fp = fileReader.GetFile();
+      if(NULL != fp)
+      {
+        if((!fseek(fp, 0, SEEK_SET)))
+        {
+          globalMap = reinterpret_cast<GifByteType*>(malloc(sizeof(GifByteType) * blobSize));
+          length    = fread(globalMap, sizeof(GifByteType), blobSize, fp);
+          succeeded = true;
+        }
+        else
+        {
+          DALI_LOG_ERROR("Error seeking within file\n");
+        }
+      }
+      else
+      {
+        DALI_LOG_ERROR("Error reading file\n");
+      }
+    }
+  }
+
+  return succeeded;
+}
+
 /**
  * @brief This combines R, G, B and Alpha values into a single 32-bit (ABGR) value.
  *
@@ -189,14 +355,14 @@ struct ImageProperties
  * @param[in] index Frame index to be searched in GIF
  * @return A pointer to the ImageFrame.
  */
-inline int CombinePixelABGR( int a, int r, int g, int b )
+inline int CombinePixelABGR(int a, int r, int g, int b)
 {
-  return ( ((a) << 24) + ((b) << 16) + ((g) << 8) + (r) );
+  return (((a) << 24) + ((b) << 16) + ((g) << 8) + (r));
 }
 
-inline int PixelLookup( ColorMapObject *colorMap, int index )
+inline int PixelLookup(ColorMapObject* colorMap, int index)
 {
-  return CombinePixelABGR( 0xFF, colorMap->Colors[index].Red, colorMap->Colors[index].Green, colorMap->Colors[index].Blue );
+  return CombinePixelABGR(0xFF, colorMap->Colors[index].Red, colorMap->Colors[index].Green, colorMap->Colors[index].Blue);
 }
 
 /**
@@ -206,13 +372,13 @@ inline int PixelLookup( ColorMapObject *colorMap, int index )
  * @param[in] index Frame index to be searched in GIF
  * @return A pointer to the ImageFrame.
  */
-ImageFrame *FindFrame( const GifAnimationData &animated, int index )
+ImageFrame* FindFrame(const GifAnimationData& animated, int index)
 {
-  for( auto &&elem : animated.frames )
+  for(auto&& elem : animated.frames)
   {
-    if( elem.index == index )
+    if(elem.index == index)
     {
-      return const_cast<ImageFrame *>( &elem );
+      return const_cast<ImageFrame*>(&elem);
     }
   }
   return nullptr;
@@ -229,15 +395,15 @@ ImageFrame *FindFrame( const GifAnimationData &animated, int index )
  * @param[in] width Width of the image
  * @param[in] height Height of the image
  */
-void FillImage( uint32_t *data, int row, uint32_t val, int x, int y, int width, int height )
+void FillImage(uint32_t* data, int row, uint32_t val, int x, int y, int width, int height)
 {
-  int xAxis, yAxis;
-  uint32_t *pixelPosition;
+  int       xAxis, yAxis;
+  uint32_tpixelPosition;
 
-  for( yAxis = 0; yAxis < height; yAxis++ )
+  for(yAxis = 0; yAxis < height; yAxis++)
   {
     pixelPosition = data + ((y + yAxis) * row) + x;
-    for( xAxis = 0; xAxis < width; xAxis++ )
+    for(xAxis = 0; xAxis < width; xAxis++)
     {
       *pixelPosition = val;
       pixelPosition++;
@@ -257,16 +423,16 @@ void FillImage( uint32_t *data, int row, uint32_t val, int x, int y, int width,
  * @param[in] width Width of the image
  * @param[in] height Height of the image
  */
-void FillFrame( uint32_t *data, int row, GifFileType *gif, FrameInfo *frameInfo, int x, int y, int w, int h )
+void FillFrame(uint32_t* data, int row, GifFileType* gif, FrameInfo* frameInfo, int x, int y, int w, int h)
 {
   // solid color fill for pre frame region
-  if( frameInfo->transparent < 0 )
+  if(frameInfo->transparent < 0)
   {
-    ColorMapObject *colorMap;
-    int backGroundColor;
+    ColorMapObjectcolorMap;
+    int             backGroundColor;
 
     // work out color to use from colorMap
-    if( gif->Image.ColorMap )
+    if(gif->Image.ColorMap)
     {
       colorMap = gif->Image.ColorMap;
     }
@@ -276,16 +442,12 @@ void FillFrame( uint32_t *data, int row, GifFileType *gif, FrameInfo *frameInfo,
     }
     backGroundColor = gif->SBackGroundColor;
     // and do the fill
-    FillImage( data, row,
-              CombinePixelABGR( 0xff, colorMap->Colors[backGroundColor].Red,
-                                colorMap->Colors[backGroundColor].Green,
-                                colorMap->Colors[backGroundColor].Blue ),
-              x, y, w, h );
+    FillImage(data, row, CombinePixelABGR(0xff, colorMap->Colors[backGroundColor].Red, colorMap->Colors[backGroundColor].Green, colorMap->Colors[backGroundColor].Blue), x, y, w, h);
   }
   // fill in region with 0 (transparent)
   else
   {
-    FillImage( data, row, 0, x, y, w, h );
+    FillImage(data, row, 0, x, y, w, h);
   }
 }
 
@@ -295,12 +457,12 @@ void FillFrame( uint32_t *data, int row, GifFileType *gif, FrameInfo *frameInfo,
  * @param[in] gif A pointer pointing to GIF File Type
  * @param[in] frameInfo A pointer pointing to Frame Information data
  */
-void StoreFrameInfo( GifFileType *gif, FrameInfo *frameInfo )
+void StoreFrameInfo(GifFileType* gif, FrameInfo* frameInfo)
 {
-  frameInfo->x = gif->Image.Left;
-  frameInfo->y = gif->Image.Top;
-  frameInfo->w = gif->Image.Width;
-  frameInfo->h = gif->Image.Height;
+  frameInfo->x         = gif->Image.Left;
+  frameInfo->y         = gif->Image.Top;
+  frameInfo->w         = gif->Image.Width;
+  frameInfo->h         = gif->Image.Height;
   frameInfo->interlace = gif->Image.Interlace;
 }
 
@@ -315,12 +477,12 @@ void StoreFrameInfo( GifFileType *gif, FrameInfo *frameInfo )
  * @param[in] width Width of the image
  * @param[in] height Height of the image
  */
-void CheckTransparency( bool &full, FrameInfo *frameInfo, int width, int height )
+void CheckTransparency(bool& full, FrameInfo* frameInfo, int width, int height)
 {
-  if( ( frameInfo->x == 0 ) && ( frameInfo->y == 0 ) &&
-      ( frameInfo->w == width ) && ( frameInfo->h == height ) )
+  if((frameInfo->x == 0) && (frameInfo->y == 0) &&
+     (frameInfo->w == width) && (frameInfo->h == height))
   {
-    if( frameInfo->transparent >= 0 )
+    if(frameInfo->transparent >= 0)
     {
       full = false;
     }
@@ -334,25 +496,25 @@ void CheckTransparency( bool &full, FrameInfo *frameInfo, int width, int height
 /**
  * @brief Fix coords and work out an x and y inset in orig data if out of image bounds.
  */
-void ClipCoordinates( int imageWidth, int imageHeight, int *xin, int *yin, int x0, int y0, int w0, int h0, int *x, int *y, int *w, int *h )
+void ClipCoordinates(int imageWidth, int imageHeight, int* xin, int* yin, int x0, int y0, int w0, int h0, int* x, int* y, int* w, int* h)
 {
-  if( x0 < 0 )
+  if(x0 < 0)
   {
     w0 += x0;
     *xin = -x0;
-    x0 = 0;
+    x0   = 0;
   }
-  if( (x0 + w0) > imageWidth )
+  if((x0 + w0) > imageWidth)
   {
     w0 = imageWidth - x0;
   }
-  if( y0 < 0 )
+  if(y0 < 0)
   {
     h0 += y0;
     *yin = -y0;
-    y0 = 0;
+    y0   = 0;
   }
-  if( (y0 + h0) > imageHeight )
+  if((y0 + h0) > imageHeight)
   {
     h0 = imageHeight - y0;
   }
@@ -373,42 +535,42 @@ void ClipCoordinates( int imageWidth, int imageHeight, int *xin, int *yin, int x
  * @param[in] prevframe The previous frame
  * @param[in] lastPreservedFrame The last preserved frame
  */
-void FlushFrames( GifAnimationData &animated, int width, int height, ImageFrame *thisframe, ImageFrame *prevframe, ImageFrame *lastPreservedFrame )
+void FlushFrames(GifAnimationData& animated, int width, int height, ImageFrame* thisframe, ImageFrame* prevframe, ImageFrame* lastPreservedFrame)
 {
-  DALI_LOG_INFO( gGifLoadingLogFilter, Debug::Concise, "FlushFrames() START \n" );
+  DALI_LOG_INFO(gGifLoadingLogFilter, Debug::Concise, "FlushFrames() START \n");
 
   // target is the amount of memory we want to be under for stored frames
   int total = 0, target = 512 * 1024;
 
   // total up the amount of memory used by stored frames for this image
-  for( auto &&frame : animated.frames )
+  for(auto&& frame : animated.frames)
   {
-    if( frame.data )
+    if(frame.data)
     {
       total++;
     }
   }
-  total *= ( width * height * sizeof( uint32_t ) );
+  total *= (width * height * sizeof(uint32_t));
 
-  DALI_LOG_INFO( gGifLoadingLogFilter, Debug::Concise, "Total used frame size: %d\n", total );
+  DALI_LOG_INFO(gGifLoadingLogFilter, Debug::Concise, "Total used frame size: %d\n", total);
 
   // If we use more than target (512k) for frames - flush
-  if( total > target )
+  if(total > target)
   {
     // Clean frames (except current and previous) until below target
-    for( auto &&frame : animated.frames )
+    for(auto&& frame : animated.frames)
     {
-      if( (frame.index != thisframe->index) && (!prevframe || frame.index != prevframe->index) &&
-          (!lastPreservedFrame || frame.index != lastPreservedFrame->index) )
+      if((frame.index != thisframe->index) && (!prevframe || frame.index != prevframe->index) &&
+         (!lastPreservedFrame || frame.index != lastPreservedFrame->index))
       {
-        if( frame.data != nullptr )
+        if(frame.data != nullptr)
         {
           delete[] frame.data;
           frame.data = nullptr;
 
           // subtract memory used and if below target - stop flush
-          total -= ( width * height * sizeof( uint32_t ) );
-          if( total < target )
+          total -= (width * height * sizeof(uint32_t));
+          if(total < target)
           {
             break;
           }
@@ -417,7 +579,7 @@ void FlushFrames( GifAnimationData &animated, int width, int height, ImageFrame
     }
   }
 
-  DALI_LOG_INFO( gGifLoadingLogFilter, Debug::Concise, "FlushFrames() END \n" );
+  DALI_LOG_INFO(gGifLoadingLogFilter, Debug::Concise, "FlushFrames() END \n");
 }
 
 /**
@@ -429,7 +591,7 @@ void FlushFrames( GifAnimationData &animated, int width, int height, ImageFrame
  * @param[in] delay The frame delay of new frame
  * @param[in] index The index of new frame
  */
-FrameInfo *NewFrame( GifAnimationData &animated, int transparent, int dispose, int delay, int index )
+FrameInfo* NewFrame(GifAnimationData& animated, int transparent, int dispose, int delay, int index)
 {
   ImageFrame frame;
 
@@ -444,92 +606,63 @@ FrameInfo *NewFrame( GifAnimationData &animated, int transparent, int dispose, i
   frame.index = index;
   // that frame is stored AT image/screen size
 
-  animated.frames.push_back( frame );
+  animated.frames.push_back(frame);
 
-  DALI_LOG_INFO( gGifLoadingLogFilter, Debug::Concise, "NewFrame: animated.frames.size() = %d\n", animated.frames.size() );
+  DALI_LOG_INFO(gGifLoadingLogFilter, Debug::Concise, "NewFrame: animated.frames.size() = %d\n", animated.frames.size());
 
-  return &( animated.frames.back().info );
-}
-
-/**
- * @brief Copy data from gif file into buffer.
- *
- * @param[in] gifFileType A pointer pointing to GIF File Type
- * @param[out] buffer A pointer to buffer containing GIF raw data
- * @param[in] len The length in bytes to be copied
- * @return The data length of the image in bytes
- */
-int FileRead( GifFileType *gifFileType, GifByteType *buffer, int length )
-{
-  LoaderInfo::FileInfo *fi = reinterpret_cast<LoaderInfo::FileInfo *>( gifFileType->UserData );
-
-  if( fi->position >= fi->length )
-  {
-    return 0; // if at or past end - no
-  }
-  if( (fi->position + length) >= fi->length )
-  {
-    length = fi->length - fi->position;
-  }
-  memcpy( buffer, fi->map + fi->position, length );
-  fi->position += length;
-  return length;
+  return &(animated.frames.back().info);
 }
 
 /**
  * @brief Decode a gif image into rows then expand to 32bit into the destination
  * data pointer.
  */
-bool DecodeImage( GifFileType *gif, uint32_t *data, int rowpix, int xin, int yin,
-                  int transparent, int x, int y, int w, int h, bool fill )
+bool DecodeImage(GifFileType* gif, uint32_t* data, int rowpix, int xin, int yin, int transparent, int x, int y, int w, int h, bool fill)
 {
-  int intoffset[] = {0, 4, 2, 1};
-  int intjump[] = {8, 8, 4, 2};
-  int i, xx, yy, pix, gifW, gifH;
-  GifRowType *rows = NULL;
-  bool ret = false;
-  ColorMapObject *colorMap;
-  uint32_t *p;
+  int             intoffset[] = {0, 4, 2, 1};
+  int             intjump[]   = {8, 8, 4, 2};
+  int             i, xx, yy, pix, gifW, gifH;
+  GifRowType*     rows = NULL;
+  bool            ret  = false;
+  ColorMapObjectcolorMap;
+  uint32_t*       p;
 
   // what we need is image size.
-  SavedImage *sp;
-  sp = &gif->SavedImages[ gif->ImageCount - 1 ];
-  if( !sp )
-  {
-    goto on_error;
-  }
+  SavedImage* sp;
+  sp = &gif->SavedImages[gif->ImageCount - 1];
 
   gifW = sp->ImageDesc.Width;
   gifH = sp->ImageDesc.Height;
 
-  if( ( gifW < w ) || ( gifH < h ) )
+  if((gifW < w) || (gifH < h))
   {
-    DALI_ASSERT_DEBUG( false && "Dimensions are bigger than the Gif image size");
+    DALI_LOG_ERROR("gifW : %d, w : %d, gifH : %d, h : %d\n", gifW, w, gifH, h);
+    DALI_ASSERT_DEBUG(false && "Dimensions are bigger than the Gif image size");
     goto on_error;
   }
 
   // build a blob of memory to have pointers to rows of pixels
   // AND store the decoded gif pixels (1 byte per pixel) as welll
-  rows = static_cast<GifRowType *>(malloc( (gifH * sizeof(GifRowType) ) + ( gifW * gifH * sizeof(GifPixelType) )));
-  if( !rows )
+  rows = static_cast<GifRowType*>(malloc((gifH * sizeof(GifRowType)) + (gifW * gifH * sizeof(GifPixelType))));
+  if(!rows)
   {
     goto on_error;
   }
 
   // fill in the pointers at the start
-  for( yy = 0; yy < gifH; yy++ )
+  for(yy = 0; yy < gifH; yy++)
   {
-    rows[yy] = reinterpret_cast<unsigned char *>(rows) + (gifH * sizeof(GifRowType)) + (yy * gifW * sizeof(GifPixelType));
+    rows[yy] = reinterpret_cast<unsigned char*>(rows) + (gifH * sizeof(GifRowType)) + (yy * gifW * sizeof(GifPixelType));
   }
 
   // if gif is interlaced, walk interlace pattern and decode into rows
-  if( gif->Image.Interlace )
+  if(gif->Image.Interlace)
   {
-    for( i = 0; i < 4; i++ )
+    for(i = 0; i < 4; i++)
     {
-      for( yy = intoffset[i]; yy < gifH; yy += intjump[i] )
+      for(yy = intoffset[i]; yy < gifH; yy += intjump[i])
       {
-        if( DGifGetLine( gif, rows[yy], gifW ) != GIF_OK )
+        if(DGifGetLine(gif, rows[yy], gifW) != GIF_OK)
         {
           goto on_error;
         }
@@ -539,9 +672,9 @@ bool DecodeImage( GifFileType *gif, uint32_t *data, int rowpix, int xin, int yin
   // normal top to bottom - decode into rows
   else
   {
-    for( yy = 0; yy < gifH; yy++ )
+    for(yy = 0; yy < gifH; yy++)
     {
-      if( DGifGetLine( gif, rows[yy], gifW ) != GIF_OK )
+      if(DGifGetLine(gif, rows[yy], gifW) != GIF_OK)
       {
         goto on_error;
       }
@@ -549,7 +682,7 @@ bool DecodeImage( GifFileType *gif, uint32_t *data, int rowpix, int xin, int yin
   }
 
   // work out what colormap to use
-  if( gif->Image.ColorMap )
+  if(gif->Image.ColorMap)
   {
     colorMap = gif->Image.ColorMap;
   }
@@ -559,20 +692,20 @@ bool DecodeImage( GifFileType *gif, uint32_t *data, int rowpix, int xin, int yin
   }
 
   // if we need to deal with transparent pixels at all...
-  if( transparent >= 0 )
+  if(transparent >= 0)
   {
     // if we are told to FILL (overwrite with transparency kept)
-    if( fill )
+    if(fill)
     {
-      for( yy = 0; yy < h; yy++ )
+      for(yy = 0; yy < h; yy++)
       {
         p = data + ((y + yy) * rowpix) + x;
-        for( xx = 0; xx < w; xx++ )
+        for(xx = 0; xx < w; xx++)
         {
           pix = rows[yin + yy][xin + xx];
-          if( pix != transparent )
+          if(pix != transparent)
           {
-            *p = PixelLookup( colorMap, pix );
+            *p = PixelLookup(colorMap, pix);
           }
           else
           {
@@ -585,15 +718,15 @@ bool DecodeImage( GifFileType *gif, uint32_t *data, int rowpix, int xin, int yin
     // paste on top with transparent pixels untouched
     else
     {
-      for( yy = 0; yy < h; yy++ )
+      for(yy = 0; yy < h; yy++)
       {
         p = data + ((y + yy) * rowpix) + x;
-        for( xx = 0; xx < w; xx++ )
+        for(xx = 0; xx < w; xx++)
         {
           pix = rows[yin + yy][xin + xx];
-          if( pix != transparent )
+          if(pix != transparent)
           {
-            *p = PixelLookup( colorMap, pix );
+            *p = PixelLookup(colorMap, pix);
           }
           p++;
         }
@@ -603,13 +736,13 @@ bool DecodeImage( GifFileType *gif, uint32_t *data, int rowpix, int xin, int yin
   else
   {
     // walk pixels without worring about transparency at all
-    for( yy = 0; yy < h; yy++ )
+    for(yy = 0; yy < h; yy++)
     {
       p = data + ((y + yy) * rowpix) + x;
-      for( xx = 0; xx < w; xx++ )
+      for(xx = 0; xx < w; xx++)
       {
         pix = rows[yin + yy][xin + xx];
-        *p = PixelLookup( colorMap, pix );
+        *p  = PixelLookup(colorMap, pix);
         p++;
       }
     }
@@ -617,9 +750,9 @@ bool DecodeImage( GifFileType *gif, uint32_t *data, int rowpix, int xin, int yin
   ret = true;
 
 on_error:
-  if( rows )
+  if(rows)
   {
-    free( rows );
+    free(rows);
   }
   return ret;
 }
@@ -632,561 +765,470 @@ on_error:
  * @param[out] error Error code
  * @return The true or false whether reading was successful or not.
  */
-bool ReadHeader( LoaderInfo &loaderInfo,
-                 ImageProperties &prop, //output struct
-                 int *error )
+bool ReadHeader(LoaderInfo&      loaderInfo,
+                ImageProperties& prop, //output struct
+                int*             error)
 {
-  GifAnimationData &animated = loaderInfo.animated;
-  LoaderInfo::FileData &fileData = loaderInfo.fileData;
-  bool ret = false;
-  LoaderInfo::FileInfo fileInfo;
-  GifRecordType rec;
-  GifFileType *gif = NULL;
+  GifAnimationData&     animated = loaderInfo.animated;
+  LoaderInfo::FileDatafileData = loaderInfo.fileData;
+  bool                  success  = false;
+  LoaderInfo::FileInfo  fileInfo;
+  GifRecordType         rec;
+
   // it is possible which gif file have error midle of frames,
   // in that case we should play gif file until meet error frame.
-  int imageNumber = 0;
-  int loopCount = -1;
-  FrameInfo *frameInfo = NULL;
-  bool full = true;
+  int        imageNumber = 0;
+  int        loopCount   = -1;
+  FrameInfo* frameInfo   = NULL;
+  bool       full        = true;
 
-  if( fileData.isLocalResource )
+  success = fileData.LoadFile();
+  if(!success || !fileData.globalMap)
   {
-    Internal::Platform::FileReader fileReader( fileData.fileName );
-    FILE *fp = fileReader.GetFile();
-    if( fp == NULL )
-    {
-      return false;
-    }
-
-    if( fseek( fp, 0, SEEK_END ) <= -1 )
-    {
-      return false;
-    }
-
-    fileData.length = ftell( fp );
-    if( fileData.length <= -1 )
-    {
-      return false;
-    }
-
-    if( ( ! fseek( fp, 0, SEEK_SET ) ) )
-    {
-      fileData.globalMap = reinterpret_cast<GifByteType*>( malloc(sizeof( GifByteType ) * fileData.length ) );
-      fileData.length = fread( fileData.globalMap, sizeof( GifByteType ), fileData.length, fp);
-      fileInfo.map = fileData.globalMap;
-    }
-    else
-    {
-      return false;
-    }
+    success = false;
+    DALI_LOG_ERROR("LOAD_ERROR_CORRUPT_FILE\n");
   }
   else
   {
-    // remote file
-    bool succeeded;
-    Dali::Vector<uint8_t> dataBuffer;
-    size_t dataSize;
-
-    succeeded = TizenPlatform::Network::DownloadRemoteFileIntoMemory( fileData.fileName, dataBuffer, dataSize,
-                                                                      MAXIMUM_DOWNLOAD_IMAGE_SIZE );
-    if( succeeded )
+    fileInfo.map      = fileData.globalMap;
+    fileInfo.length   = fileData.length;
+    fileInfo.position = 0;
+    GifAccessor gifAccessor(fileInfo);
+
+    if(gifAccessor.gif)
     {
-      size_t blobSize = dataBuffer.Size();
-      if( blobSize > 0U )
+      // get the gif "screen size" (the actual image size)
+      prop.w = gifAccessor.gif->SWidth;
+      prop.h = gifAccessor.gif->SHeight;
+
+      // if size is invalid - abort here
+      if((prop.w < 1) || (prop.h < 1) || (prop.w > IMG_MAX_SIZE) || (prop.h > IMG_MAX_SIZE) || IMG_TOO_BIG(prop.w, prop.h))
       {
-        // Open a file handle on the memory buffer:
-        Dali::Internal::Platform::FileReader fileReader( dataBuffer, blobSize );
-        FILE * const fp = fileReader.GetFile();
-        if ( NULL != fp )
+        if(IMG_TOO_BIG(prop.w, prop.h))
         {
-          if( ( ! fseek( fp, 0, SEEK_SET ) ) )
-          {
-            fileData.globalMap = reinterpret_cast<GifByteType*>( malloc(sizeof( GifByteType ) * blobSize ) );
-            fileData.length = fread( fileData.globalMap, sizeof( GifByteType ), blobSize, fp);
-            fileInfo.map = fileData.globalMap;
-          }
-          else
-          {
-            DALI_LOG_ERROR( "Error seeking within file\n" );
-          }
+          success = false;
+          DALI_LOG_ERROR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
         }
         else
         {
-          DALI_LOG_ERROR( "Error reading file\n" );
+          success = false;
+          DALI_LOG_ERROR("LOAD_ERROR_GENERIC");
         }
       }
-    }
-  }
-
-  if( !fileInfo.map )
-  {
-    LOADERR("LOAD_ERROR_CORRUPT_FILE");
-  }
-  fileInfo.length = fileData.length;
-  fileInfo.position = 0;
-
-// actually ask libgif to open the file
-#if GIFLIB_MAJOR >= 5
-  gif = DGifOpen( &fileInfo, FileRead, NULL );
-#else
-  gif = DGifOpen( &fileInfo, FileRead );
-#endif
-
-  if (!gif)
-  {
-    LOADERR("LOAD_ERROR_UNKNOWN_FORMAT");
-  }
-
-  // get the gif "screen size" (the actual image size)
-  prop.w = gif->SWidth;
-  prop.h = gif->SHeight;
-
-  // if size is invalid - abort here
-  if( (prop.w < 1) || (prop.h < 1) || (prop.w > IMG_MAX_SIZE) || (prop.h > IMG_MAX_SIZE) || IMG_TOO_BIG(prop.w, prop.h) )
-  {
-    if( IMG_TOO_BIG(prop.w, prop.h) )
-    {
-      LOADERR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
-    }
-    LOADERR("LOAD_ERROR_GENERIC");
-  }
-  // walk through gif records in file to figure out info
-  do
-  {
-    if( DGifGetRecordType(gif, &rec) == GIF_ERROR )
-    {
-      // if we have a gif that ends part way through a sequence
-      // (or animation) consider it valid and just break - no error
-      if( imageNumber > 1 )
-      {
-        break;
-      }
-      LOADERR("LOAD_ERROR_UNKNOWN_FORMAT");
-    }
-
-    // get image description section
-    if( rec == IMAGE_DESC_RECORD_TYPE )
-    {
-      int img_code;
-      GifByteType *img;
-
-      // get image desc
-      if( DGifGetImageDesc(gif) == GIF_ERROR )
-      {
-        LOADERR("LOAD_ERROR_UNKNOWN_FORMAT");
-      }
-      // skip decoding and just walk image to next
-      if( DGifGetCode(gif, &img_code, &img) == GIF_ERROR )
-      {
-        LOADERR("LOAD_ERROR_UNKNOWN_FORMAT");
-      }
-      // skip till next...
-      while( img )
-      {
-        img = NULL;
-        DGifGetCodeNext( gif, &img );
-      }
-      // store geometry in the last frame info data
-      if( frameInfo )
-      {
-        StoreFrameInfo( gif, frameInfo );
-        CheckTransparency( full, frameInfo, prop.w, prop.h );
-      }
-      // or if we dont have a frameInfo entry - create one even for stills
       else
       {
-        // allocate and save frame with field data
-        frameInfo = NewFrame( animated, -1, 0, 0, imageNumber + 1 );
-        if (!frameInfo)
+        // walk through gif records in file to figure out info
+        success = true;
+        do
         {
-          LOADERR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
-        }
-        // store geometry info from gif image
-        StoreFrameInfo( gif, frameInfo );
-        // check for transparency/alpha
-        CheckTransparency( full, frameInfo, prop.w, prop.h );
-      }
-      imageNumber++;
-    }
-    // we have an extension code block - for animated gifs for sure
-    else if( rec == EXTENSION_RECORD_TYPE )
-    {
-      int ext_code;
-      GifByteType *ext;
-
-      ext = NULL;
-      // get the first extension entry
-      DGifGetExtension( gif, &ext_code, &ext );
-      while( ext )
-      {
-        // graphic control extension - for animated gif data
-        // and transparent index + flag
-        if( ext_code == 0xf9 )
-        {
-          // create frame and store it in image
-          int transparencyIndex = (ext[1] & 1) ? ext[4] : -1;
-          int disposeMode = (ext[1] >> 2) & 0x7;
-          int delay = (int(ext[3]) << 8) | int(ext[2]);
-          frameInfo = NewFrame(animated, transparencyIndex, disposeMode, delay, imageNumber + 1);
-          if( !frameInfo )
+          if(DGifGetRecordType(gifAccessor.gif, &rec) == GIF_ERROR)
           {
-            LOADERR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
+            // if we have a gif that ends part way through a sequence
+            // (or animation) consider it valid and just break - no error
+            if(imageNumber <= 1)
+            {
+              success = true;
+            }
+            else
+            {
+              success = false;
+              DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+            }
+            break;
           }
-        }
-        // netscape extension indicating loop count.
-        else if( ext_code == 0xff ) /* application extension */
-        {
-          if( !strncmp(reinterpret_cast<char *>(&ext[1]), "NETSCAPE2.0", 11) ||
-              !strncmp(reinterpret_cast<char *>(&ext[1]), "ANIMEXTS1.0", 11) )
+
+          // get image description section
+          if(rec == IMAGE_DESC_RECORD_TYPE)
           {
-            ext = NULL;
-            DGifGetExtensionNext( gif, &ext );
-            if( ext[1] == 0x01 )
+            int          img_code;
+            GifByteType* img;
+
+            // get image desc
+            if(DGifGetImageDesc(gifAccessor.gif) == GIF_ERROR)
+            {
+              success = false;
+              DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+              break;
+            }
+            // skip decoding and just walk image to next
+            if(DGifGetCode(gifAccessor.gif, &img_code, &img) == GIF_ERROR)
+            {
+              success = false;
+              DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+              break;
+            }
+            // skip till next...
+            while(img)
+            {
+              img = NULL;
+              DGifGetCodeNext(gifAccessor.gif, &img);
+            }
+            // store geometry in the last frame info data
+            if(frameInfo)
+            {
+              StoreFrameInfo(gifAccessor.gif, frameInfo);
+              CheckTransparency(full, frameInfo, prop.w, prop.h);
+            }
+            // or if we dont have a frameInfo entry - create one even for stills
+            else
             {
-              loopCount = (int(ext[3]) << 8) | int(ext[2]);
-              if( loopCount > 0 )
+              // allocate and save frame with field data
+              frameInfo = NewFrame(animated, -1, 0, 0, imageNumber + 1);
+              if(!frameInfo)
               {
-                loopCount++;
+                success = false;
+                DALI_LOG_ERROR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
+                break;
               }
+              // store geometry info from gif image
+              StoreFrameInfo(gifAccessor.gif, frameInfo);
+              // check for transparency/alpha
+              CheckTransparency(full, frameInfo, prop.w, prop.h);
             }
+            imageNumber++;
           }
-        }
-        // and continue onto the next extension entry
-        ext = NULL;
-        DGifGetExtensionNext( gif, &ext );
-      }
-    }
-  } while( rec != TERMINATE_RECORD_TYPE );
+          // we have an extension code block - for animated gifs for sure
+          else if(rec == EXTENSION_RECORD_TYPE)
+          {
+            int          ext_code;
+            GifByteType* ext = NULL;
 
-  // if the gif main says we have more than one image or our image counting
-  // says so, then this image is animated - indicate this
-  if( (gif->ImageCount > 1) || (imageNumber > 1) )
-  {
-    animated.animated = 1;
-    animated.loopCount = loopCount;
-  }
-  animated.frameCount = std::min( gif->ImageCount, imageNumber );
+            // get the first extension entry
+            DGifGetExtension(gifAccessor.gif, &ext_code, &ext);
+            while(ext)
+            {
+              // graphic control extension - for animated gif data
+              // and transparent index + flag
+              if(ext_code == 0xf9)
+              {
+                // create frame and store it in image
+                int transparencyIndex = (ext[1] & 1) ? ext[4] : -1;
+                int disposeMode       = (ext[1] >> 2) & 0x7;
+                int delay             = (int(ext[3]) << 8) | int(ext[2]);
+                frameInfo             = NewFrame(animated, transparencyIndex, disposeMode, delay, imageNumber + 1);
+                if(!frameInfo)
+                {
+                  success = false;
+                  DALI_LOG_ERROR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
+                  break;
+                }
+              }
+              // netscape extension indicating loop count.
+              else if(ext_code == 0xff) /* application extension */
+              {
+                if(!strncmp(reinterpret_cast<char*>(&ext[1]), "NETSCAPE2.0", 11) ||
+                   !strncmp(reinterpret_cast<char*>(&ext[1]), "ANIMEXTS1.0", 11))
+                {
+                  ext = NULL;
+                  DGifGetExtensionNext(gifAccessor.gif, &ext);
+                  if(ext[1] == 0x01)
+                  {
+                    loopCount = (int(ext[3]) << 8) | int(ext[2]);
+                    if(loopCount > 0)
+                    {
+                      loopCount++;
+                    }
+                  }
+                }
+              }
 
-  if( !full )
-  {
-    prop.alpha = 1;
-  }
+              // and continue onto the next extension entry
+              ext = NULL;
+              DGifGetExtensionNext(gifAccessor.gif, &ext);
+            }
+          }
+        } while(rec != TERMINATE_RECORD_TYPE && success);
 
-  animated.currentFrame = 1;
+        if(success)
+        {
+          // if the gif main says we have more than one image or our image counting
+          // says so, then this image is animated - indicate this
+          if((gifAccessor.gif->ImageCount > 1) || (imageNumber > 1))
+          {
+            animated.animated  = 1;
+            animated.loopCount = loopCount;
+          }
+          animated.frameCount = std::min(gifAccessor.gif->ImageCount, imageNumber);
 
-  // no errors in header scan etc. so set err and return value
-  *error = 0;
-  ret = true;
+          if(!full)
+          {
+            prop.alpha = 1;
+          }
 
-on_error: // jump here on any errors to clean up
-#if (GIFLIB_MAJOR > 5) || ((GIFLIB_MAJOR == 5) && (GIFLIB_MINOR >= 1))
-  if( gif )
-  {
-    DGifCloseFile( gif, NULL );
-  }
-#else
-  if( gif )
-  {
-    DGifCloseFile( gif );
-  }
-#endif
+          animated.currentFrame = 1;
 
-  return ret;
+          // no errors in header scan etc. so set err and return value
+          *error = 0;
+        }
+      }
+    }
+  }
+  return success;
 }
 
 /**
  * @brief Reader next frame of the gif file and populates structures accordingly.
  *
- * @param[in] loaderInfo A LoaderInfo structure containing file descriptor and other data about GIF.
- * @param[in/out] prop A ImageProperties structure containing information about gif data.
+ * @param[in,out] loaderInfo A LoaderInfo structure containing file descriptor and other data about GIF.
+ * @param[in,out] prop A ImageProperties structure containing information about gif data.
  * @param[out] pixels A pointer to buffer which will contain all pixel data of the frame on return.
  * @param[out] error Error code
  * @return The true or false whether reading was successful or not.
  */
-bool ReadNextFrame( LoaderInfo &loaderInfo, ImageProperties &prop, //  use for w and h
-                    unsigned char *pixels, int *error )
+bool ReadNextFrame(LoaderInfo& loaderInfo, ImageProperties& prop, //  use for w and h
+                   unsigned char* pixels,
+                   int*           error)
 {
-  GifAnimationData &animated = loaderInfo.animated;
-  LoaderInfo::FileData &fileData = loaderInfo.fileData;
-  bool ret = false;
-  GifRecordType rec;
-  GifFileType *gif = NULL;
-  int index = 0, imageNumber = 0;
-  FrameInfo *frameInfo;
-  ImageFrame *frame = NULL;
-  ImageFrame *lastPreservedFrame = NULL;
+  GifAnimationData&     animated = loaderInfo.animated;
+  LoaderInfo::FileData& fileData = loaderInfo.fileData;
+  bool                  ret      = false;
+  GifRecordType         rec;
+  int                   index = 0, imageNumber = 0;
+  FrameInfo*            frameInfo;
+  ImageFrame*           frame              = NULL;
+  ImageFrame*           lastPreservedFrame = NULL;
 
   index = animated.currentFrame;
 
   // if index is invalid for animated image - error out
-  if ((animated.animated) && ((index <= 0) || (index > animated.frameCount)))
+  if((animated.animated) && ((index <= 0) || (index > animated.frameCount)))
   {
-    LOADERR("LOAD_ERROR_GENERIC");
+    DALI_LOG_ERROR("LOAD_ERROR_GENERIC");
+    return false;
   }
 
   // find the given frame index
-  frame = FindFrame( animated, index );
-  if( frame )
-  {
-    if( (frame->loaded) && (frame->data) )
-    {
-      // frame is already there and decoded - jump to end
-      goto on_ok;
-    }
-  }
-  else
+  frame = FindFrame(animated, index);
+  if(!frame)
   {
-    LOADERR("LOAD_ERROR_CORRUPT_FILE");
+    DALI_LOG_ERROR("LOAD_ERROR_CORRUPT_FILE\n");
+    return false;
   }
-
-open_file:
-  // actually ask libgif to open the file
-  gif = loaderInfo.gif;
-  if( !gif )
+  else if(!(frame->loaded) || !(frame->data))
   {
-    loaderInfo.fileInfo.map = fileData.globalMap ;
-    if( !loaderInfo.fileInfo.map )
+    // if we want to go backwards, we likely need/want to re-decode from the
+    // start as we have nothing to build on. If there is a gif, imageNumber
+    // has been set already.
+    if(loaderInfo.gifAccessor && loaderInfo.imageNumber > 0)
     {
-      LOADERR("LOAD_ERROR_CORRUPT_FILE");
-    }
-    loaderInfo.fileInfo.length = fileData.length;
-    loaderInfo.fileInfo.position = 0;
-
-#if GIFLIB_MAJOR >= 5
-    gif = DGifOpen( &( loaderInfo.fileInfo ), FileRead, NULL );
-#else
-    gif = DGifOpen( &( loaderInfo.fileInfo ), FileRead );
-#endif
-    // if gif open failed... get out of here
-    if( !gif )
-    {
-      LOADERR("LOAD_ERROR_UNKNOWN_FORMAT");
-    }
-    loaderInfo.gif = gif;
-    loaderInfo.imageNumber = 1;
-  }
-
-  // if we want to go backwards, we likely need/want to re-decode from the
-  // start as we have nothing to build on
-  if( (index > 0) && (index < loaderInfo.imageNumber) && (animated.animated) )
-  {
-#if (GIFLIB_MAJOR > 5) || ((GIFLIB_MAJOR == 5) && (GIFLIB_MINOR >= 1))
-    if( loaderInfo.gif )
-      DGifCloseFile( loaderInfo.gif, NULL );
-#else
-    if( loaderInfo.gif )
-      DGifCloseFile( loaderInfo.gif );
-#endif
-    loaderInfo.gif = NULL;
-    loaderInfo.imageNumber = 0;
-    goto open_file;
-  }
-
-  // our current position is the previous frame we decoded from the file
-  imageNumber = loaderInfo.imageNumber;
-
-  // walk through gif records in file to figure out info
-  do
-  {
-    if( DGifGetRecordType( gif, &rec ) == GIF_ERROR )
-    {
-      LOADERR("LOAD_ERROR_UNKNOWN_FORMAT");
+      if((index > 0) && (index < loaderInfo.imageNumber) && (animated.animated))
+      {
+        loaderInfo.gifAccessor.reset();
+        loaderInfo.imageNumber = 0;
+      }
     }
 
-    if( rec == EXTENSION_RECORD_TYPE )
+    // actually ask libgif to open the file
+    if(!loaderInfo.gifAccessor)
     {
-      int ext_code;
-      GifByteType *ext = NULL;
-      DGifGetExtension( gif, &ext_code, &ext );
-
-      while( ext )
+      loaderInfo.fileInfo.map      = fileData.globalMap;
+      loaderInfo.fileInfo.length   = fileData.length;
+      loaderInfo.fileInfo.position = 0;
+      if(!loaderInfo.fileInfo.map)
       {
-        ext = NULL;
-        DGifGetExtensionNext( gif, &ext );
+        DALI_LOG_ERROR("LOAD_ERROR_CORRUPT_FILE\n");
+        return false;
       }
-    }
-    // get image description section
-    else if( rec == IMAGE_DESC_RECORD_TYPE )
-    {
-      int xin = 0, yin = 0, x = 0, y = 0, w = 0, h = 0;
-      int img_code;
-      GifByteType *img;
-      ImageFrame *previousFrame = NULL;
-      ImageFrame *thisFrame = NULL;
-
-      // get image desc
-      if( DGifGetImageDesc(gif) == GIF_ERROR )
+      std::unique_ptr<GifAccessor> gifAccessor = std::make_unique<GifAccessor>(loaderInfo.fileInfo);
+      if(!gifAccessor->gif)
       {
-        LOADERR("LOAD_ERROR_UNKNOWN_FORMAT");
+        DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+        return false;
       }
+      loaderInfo.gifAccessor = std::move(gifAccessor);
+      loaderInfo.imageNumber = 1;
+    }
 
-      // get the previous frame entry AND the current one to fill in
-      previousFrame = FindFrame(animated, imageNumber - 1);
-      thisFrame = FindFrame(animated, imageNumber);
+    // our current position is the previous frame we decoded from the file
+    imageNumber = loaderInfo.imageNumber;
 
-      // if we have a frame AND we're animated AND we have no data...
-      if( (thisFrame) && (!thisFrame->data) && (animated.animated) )
+    // walk through gif records in file to figure out info
+    do
+    {
+      if(DGifGetRecordType(loaderInfo.gifAccessor->gif, &rec) == GIF_ERROR)
       {
-        bool first = false;
+        DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+        return false;
+      }
 
-        // allocate it
-        thisFrame->data = new uint32_t[prop.w * prop.h];
+      if(rec == EXTENSION_RECORD_TYPE)
+      {
+        int          ext_code;
+        GifByteType* ext = NULL;
+        DGifGetExtension(loaderInfo.gifAccessor->gif, &ext_code, &ext);
 
-        if( !thisFrame->data )
+        while(ext)
         {
-          LOADERR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
+          ext = NULL;
+          DGifGetExtensionNext(loaderInfo.gifAccessor->gif, &ext);
         }
-
-        // if we have no prior frame OR prior frame data... empty
-        if( (!previousFrame) || (!previousFrame->data) )
+      }
+      // get image description section
+      else if(rec == IMAGE_DESC_RECORD_TYPE)
+      {
+        int          xin = 0, yin = 0, x = 0, y = 0, w = 0, h = 0;
+        int          img_code;
+        GifByteType* img;
+        ImageFrame*  previousFrame = NULL;
+        ImageFrame*  thisFrame     = NULL;
+
+        // get image desc
+        if(DGifGetImageDesc(loaderInfo.gifAccessor->gif) == GIF_ERROR)
         {
-          first = true;
-          frameInfo = &(thisFrame->info);
-          memset( thisFrame->data, 0, prop.w * prop.h * sizeof(uint32_t) );
+          DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+          return false;
         }
-        // we have a prior frame to copy data from...
-        else
+
+        // get the previous frame entry AND the current one to fill in
+        previousFrame = FindFrame(animated, imageNumber - 1);
+        thisFrame     = FindFrame(animated, imageNumber);
+
+        // if we have a frame AND we're animated AND we have no data...
+        if((thisFrame) && (!thisFrame->data) && (animated.animated))
         {
-          frameInfo = &( previousFrame->info );
+          bool first = false;
 
-          // fix coords of sub image in case it goes out...
-          ClipCoordinates( prop.w, prop.h, &xin, &yin,
-                           frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h,
-                           &x, &y, &w, &h );
+          // allocate it
+          thisFrame->data = new uint32_t[prop.w * prop.h];
 
-          // if dispose mode is not restore - then copy pre frame
-          if( frameInfo->dispose != DISPOSE_PREVIOUS )
+          if(!thisFrame->data)
           {
-            memcpy( thisFrame->data, previousFrame->data, prop.w * prop.h * sizeof(uint32_t) );
+            DALI_LOG_ERROR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
+            return false;
           }
 
-          // if dispose mode is "background" then fill with bg
-          if( frameInfo->dispose == DISPOSE_BACKGROUND )
+          // if we have no prior frame OR prior frame data... empty
+          if((!previousFrame) || (!previousFrame->data))
           {
-            FillFrame( thisFrame->data, prop.w, gif, frameInfo, x, y, w, h );
+            first     = true;
+            frameInfo = &(thisFrame->info);
+            memset(thisFrame->data, 0, prop.w * prop.h * sizeof(uint32_t));
           }
-          else if( frameInfo->dispose == DISPOSE_PREVIOUS ) // GIF_DISPOSE_RESTORE
+          // we have a prior frame to copy data from...
+          else
           {
-            int prevIndex = 2;
-            do
+            frameInfo = &(previousFrame->info);
+
+            // fix coords of sub image in case it goes out...
+            ClipCoordinates(prop.w, prop.h, &xin, &yin, frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h, &x, &y, &w, &h);
+
+            // if dispose mode is not restore - then copy pre frame
+            if(frameInfo->dispose != DISPOSE_PREVIOUS)
             {
-              // Find last preserved frame.
-              lastPreservedFrame = FindFrame( animated, imageNumber - prevIndex );
-              if( ! lastPreservedFrame )
-              {
-                LOADERR( "LOAD_ERROR_LAST_PRESERVED_FRAME_NOT_FOUND" );
-              }
-              prevIndex++;
-            } while( lastPreservedFrame && lastPreservedFrame->info.dispose == DISPOSE_PREVIOUS );
+              memcpy(thisFrame->data, previousFrame->data, prop.w * prop.h * sizeof(uint32_t));
+            }
 
-            if ( lastPreservedFrame )
+            // if dispose mode is "background" then fill with bg
+            if(frameInfo->dispose == DISPOSE_BACKGROUND)
+            {
+              FillFrame(thisFrame->data, prop.w, loaderInfo.gifAccessor->gif, frameInfo, x, y, w, h);
+            }
+            else if(frameInfo->dispose == DISPOSE_PREVIOUS) // GIF_DISPOSE_RESTORE
             {
-              memcpy( thisFrame->data, lastPreservedFrame->data, prop.w * prop.h * sizeof(uint32_t) );
+              int prevIndex = 2;
+              do
+              {
+                // Find last preserved frame.
+                lastPreservedFrame = FindFrame(animated, imageNumber - prevIndex);
+                if(!lastPreservedFrame)
+                {
+                  DALI_LOG_ERROR("LOAD_ERROR_LAST_PRESERVED_FRAME_NOT_FOUND");
+                  return false;
+                }
+                prevIndex++;
+              } while(lastPreservedFrame && lastPreservedFrame->info.dispose == DISPOSE_PREVIOUS);
+
+              if(lastPreservedFrame)
+              {
+                memcpy(thisFrame->data, lastPreservedFrame->data, prop.w * prop.h * sizeof(uint32_t));
+              }
             }
           }
+          // now draw this frame on top
+          frameInfo = &(thisFrame->info);
+          ClipCoordinates(prop.w, prop.h, &xin, &yin, frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h, &x, &y, &w, &h);
+          if(!DecodeImage(loaderInfo.gifAccessor->gif, thisFrame->data, prop.w, xin, yin, frameInfo->transparent, x, y, w, h, first))
+          {
+            DALI_LOG_ERROR("LOAD_ERROR_CORRUPT_FILE\n");
+            return false;
+          }
+
+          // mark as loaded and done
+          thisFrame->loaded = true;
+
+          FlushFrames(animated, prop.w, prop.h, thisFrame, previousFrame, lastPreservedFrame);
         }
-        // now draw this frame on top
-        frameInfo = &( thisFrame->info );
-        ClipCoordinates( prop.w, prop.h, &xin, &yin,
-                         frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h,
-                         &x, &y, &w, &h );
-        if( !DecodeImage( gif, thisFrame->data, prop.w,
-                          xin, yin, frameInfo->transparent,
-                          x, y, w, h, first) )
+        // if we have a frame BUT the image is not animated. different
+        // path
+        else if((thisFrame) && (!thisFrame->data) && (!animated.animated))
         {
-          LOADERR("LOAD_ERROR_CORRUPT_FILE");
-        }
+          // if we don't have the data decoded yet - decode it
+          if((!thisFrame->loaded) || (!thisFrame->data))
+          {
+            // use frame info but we WONT allocate frame pixels
+            frameInfo = &(thisFrame->info);
+            ClipCoordinates(prop.w, prop.h, &xin, &yin, frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h, &x, &y, &w, &h);
 
-        // mark as loaded and done
-        thisFrame->loaded = true;
+            // clear out all pixels
+            FillFrame(reinterpret_cast<uint32_t*>(pixels), prop.w, loaderInfo.gifAccessor->gif, frameInfo, 0, 0, prop.w, prop.h);
 
-        FlushFrames( animated, prop.w, prop.h, thisFrame, previousFrame, lastPreservedFrame );
-      }
-      // if we have a frame BUT the image is not animated. different
-      // path
-      else if( (thisFrame) && (!thisFrame->data) && (!animated.animated) )
-      {
-        // if we don't have the data decoded yet - decode it
-        if( (!thisFrame->loaded) || (!thisFrame->data) )
+            // and decode the gif with overwriting
+            if(!DecodeImage(loaderInfo.gifAccessor->gif, reinterpret_cast<uint32_t*>(pixels), prop.w, xin, yin, frameInfo->transparent, x, y, w, h, true))
+            {
+              DALI_LOG_ERROR("LOAD_ERROR_CORRUPT_FILE\n");
+              return false;
+            }
+
+            // mark as loaded and done
+            thisFrame->loaded = true;
+          }
+          // flush mem we don't need (at expense of decode cpu)
+        }
+        else
         {
-          // use frame info but we WONT allocate frame pixels
-          frameInfo = &( thisFrame->info );
-          ClipCoordinates( prop.w, prop.h, &xin, &yin,
-                           frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h,
-                           &x, &y, &w, &h );
-
-          // clear out all pixels
-          FillFrame( reinterpret_cast<uint32_t *>(pixels), prop.w, gif, frameInfo, 0, 0, prop.w, prop.h );
-
-          // and decode the gif with overwriting
-          if( !DecodeImage( gif, reinterpret_cast<uint32_t *>(pixels), prop.w,
-                            xin, yin, frameInfo->transparent, x, y, w, h, true) )
+          // skip decoding and just walk image to next
+          if(DGifGetCode(loaderInfo.gifAccessor->gif, &img_code, &img) == GIF_ERROR)
           {
-            LOADERR("LOAD_ERROR_CORRUPT_FILE");
+            DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+            return false;
           }
 
-          // mark as loaded and done
-          thisFrame->loaded = true;
-        }
-        // flush mem we don't need (at expense of decode cpu)
-      }
-      else
-      {
-        // skip decoding and just walk image to next
-        if( DGifGetCode( gif, &img_code, &img ) == GIF_ERROR )
-        {
-          LOADERR("LOAD_ERROR_UNKNOWN_FORMAT");
+          while(img)
+          {
+            img = NULL;
+            DGifGetCodeNext(loaderInfo.gifAccessor->gif, &img);
+          }
         }
 
-        while( img )
+        imageNumber++;
+        // if we found the image we wanted - get out of here
+        if(imageNumber > index)
         {
-          img = NULL;
-          DGifGetCodeNext( gif, &img );
+          break;
         }
       }
+    } while(rec != TERMINATE_RECORD_TYPE);
 
-      imageNumber++;
-      // if we found the image we wanted - get out of here
-      if( imageNumber > index )
-      {
-        break;
-      }
-    }
-  } while( rec != TERMINATE_RECORD_TYPE );
-
-  // if we are at the end of the animation or not animated, close file
-  loaderInfo.imageNumber = imageNumber;
-  if( (animated.frameCount <= 1) || (rec == TERMINATE_RECORD_TYPE) )
-  {
-#if (GIFLIB_MAJOR > 5) || ((GIFLIB_MAJOR == 5) && (GIFLIB_MINOR >= 1))
-    if( loaderInfo.gif )
-    {
-      DGifCloseFile( loaderInfo.gif, NULL );
-    }
-#else
-    if( loaderInfo.gif )
+    // if we are at the end of the animation or not animated, close file
+    loaderInfo.imageNumber = imageNumber;
+    if((animated.frameCount <= 1) || (rec == TERMINATE_RECORD_TYPE))
     {
-      DGifCloseFile( loaderInfo.gif );
+      loaderInfo.gifAccessor.reset();
+      loaderInfo.imageNumber = 0;
     }
-#endif
-
-    loaderInfo.gif = NULL;
-    loaderInfo.imageNumber = 0;
   }
 
-on_ok:
   // no errors in header scan etc. so set err and return value
   *error = 0;
-  ret = true;
+  ret    = true;
 
   // if it was an animated image we need to copy the data to the
   // pixels for the image from the frame holding the data
-  if( animated.animated && frame->data )
+  if(animated.animated && frame->data)
   {
-    memcpy( pixels, frame->data, prop.w * prop.h * sizeof( uint32_t ) );
+    memcpy(pixels, frame->data, prop.w * prop.h * sizeof(uint32_t));
   }
 
-on_error: // jump here on any errors to clean up
   return ret;
 }
 
@@ -1195,87 +1237,77 @@ on_error: // jump here on any errors to clean up
 struct GifLoading::Impl
 {
 public:
-  Impl( const std::string& url, bool isLocalResource )
-  : mUrl( url )
+  Impl(const std::string& url, bool isLocalResource)
+  : mUrl(url),
+    mLoadSucceeded(true),
+    mMutex()
   {
-    loaderInfo.gif = nullptr;
+    loaderInfo.gifAccessor = nullptr;
     int error;
-    loaderInfo.fileData.fileName = mUrl.c_str();
+    loaderInfo.fileData.fileName        = mUrl.c_str();
     loaderInfo.fileData.isLocalResource = isLocalResource;
 
-    ReadHeader( loaderInfo, imageProperties, &error );
+    mLoadSucceeded = ReadHeader(loaderInfo, imageProperties, &error);
   }
 
   // Moveable but not copyable
+  Impl(const Impl&) = delete;
+  Impl& operator=(const Impl&) = delete;
+  Impl(Impl&&)                 = default;
+  Impl& operator=(Impl&&) = default;
 
-  Impl( const Impl& ) = delete;
-  Impl& operator=( const Impl& ) = delete;
-  Impl( Impl&& ) = default;
-  Impl& operator=( Impl&& ) = default;
-
-  ~Impl()
-  {
-    if( loaderInfo.fileData.globalMap  )
-    {
-      free( loaderInfo.fileData.globalMap );
-      loaderInfo.fileData.globalMap  = nullptr;
-    }
-
-    // Delete all image frames
-    for( auto &&frame : loaderInfo.animated.frames )
-    {
-      if( frame.data != nullptr )
-      {
-        // De-allocate memory of the frame data.
-        delete[] frame.data;
-        frame.data = nullptr;
-      }
-    }
-  }
-
-  std::string mUrl;
-  LoaderInfo loaderInfo;
+  std::string     mUrl;
+  LoaderInfo      loaderInfo;
   ImageProperties imageProperties;
+  bool            mLoadSucceeded;
+  Mutex           mMutex;
 };
 
-AnimatedImageLoadingPtr GifLoading::New( const std::string &url, bool isLocalResource )
+AnimatedImageLoadingPtr GifLoading::New(const std::string& url, bool isLocalResource)
 {
-  return AnimatedImageLoadingPtr( new GifLoading( url, isLocalResource ) );
+  return AnimatedImageLoadingPtr(new GifLoading(url, isLocalResource));
 }
 
-GifLoading::GifLoading( const std::string &url, bool isLocalResource )
-: mImpl( new GifLoading::Impl( url, isLocalResource ) )
+GifLoading::GifLoading(const std::string& url, bool isLocalResource)
+: mImpl(new GifLoading::Impl(url, isLocalResource))
 {
 }
 
-
 GifLoading::~GifLoading()
 {
   delete mImpl;
 }
 
-bool GifLoading::LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector<Dali::PixelData> &pixelData )
+bool GifLoading::LoadNextNFrames(uint32_t frameStartIndex, int count, std::vector<Dali::PixelData>& pixelData)
 {
-  int error;
+  int  error;
   bool ret = false;
+  if(!mImpl->mLoadSucceeded)
+  {
+    return false;
+  }
+
+  Mutex::ScopedLock lock(mImpl->mMutex);
+  if(!mImpl->mLoadSucceeded)
+  {
+    return false;
+  }
 
-  const int bufferSize = mImpl->imageProperties.w * mImpl->imageProperties.h * sizeof( uint32_t );
+  const int bufferSize = mImpl->imageProperties.w * mImpl->imageProperties.h * sizeof(uint32_t);
 
-  DALI_LOG_INFO( gGifLoadingLogFilter, Debug::Concise, "LoadNextNFrames( frameStartIndex:%d, count:%d )\n", frameStartIndex, count );
+  DALI_LOG_INFO(gGifLoadingLogFilter, Debug::Concise, "LoadNextNFrames( frameStartIndex:%d, count:%d )\n", frameStartIndex, count);
 
-  for( int i = 0; i < count; ++i )
+  for(int i = 0; i < count; ++i)
   {
-    auto pixelBuffer = new unsigned char[ bufferSize ];
+    auto pixelBuffer = new unsigned char[bufferSize];
 
-    mImpl->loaderInfo.animated.currentFrame = 1 + ( (frameStartIndex + i) % mImpl->loaderInfo.animated.frameCount );
+    mImpl->loaderInfo.animated.currentFrame = 1 + ((frameStartIndex + i) % mImpl->loaderInfo.animated.frameCount);
 
-    if( ReadNextFrame( mImpl->loaderInfo, mImpl->imageProperties, pixelBuffer, &error ) )
+    if(ReadNextFrame(mImpl->loaderInfo, mImpl->imageProperties, pixelBuffer, &error))
     {
-      if( pixelBuffer )
+      if(pixelBuffer)
       {
-        pixelData.push_back( Dali::PixelData::New( pixelBuffer, bufferSize,
-                                                   mImpl->imageProperties.w, mImpl->imageProperties.h,
-                                                   Dali::Pixel::RGBA8888, Dali::PixelData::DELETE_ARRAY) );
+        pixelData.push_back(Dali::PixelData::New(pixelBuffer, bufferSize, mImpl->imageProperties.w, mImpl->imageProperties.h, Dali::Pixel::RGBA8888, Dali::PixelData::DELETE_ARRAY));
         ret = true;
       }
     }
@@ -1284,19 +1316,24 @@ bool GifLoading::LoadNextNFrames( uint32_t frameStartIndex, int count, std::vect
   return ret;
 }
 
-Dali::Devel::PixelBuffer GifLoading::LoadFrame( uint32_t frameIndex )
+Dali::Devel::PixelBuffer GifLoading::LoadFrame(uint32_t frameIndex)
 {
-  int error;
+  int                      error;
   Dali::Devel::PixelBuffer pixelBuffer;
+  if(!mImpl->mLoadSucceeded)
+  {
+    return pixelBuffer;
+  }
 
-  DALI_LOG_INFO( gGifLoadingLogFilter, Debug::Concise, "LoadFrame( frameIndex:%d )\n", frameIndex );
+  Mutex::ScopedLock lock(mImpl->mMutex);
+  DALI_LOG_INFO(gGifLoadingLogFilter, Debug::Concise, "LoadFrame( frameIndex:%d )\n", frameIndex);
 
-  pixelBuffer = Dali::Devel::PixelBuffer::New( mImpl->imageProperties.w, mImpl->imageProperties.h, Dali::Pixel::RGBA8888 );
+  pixelBuffer = Dali::Devel::PixelBuffer::New(mImpl->imageProperties.w, mImpl->imageProperties.h, Dali::Pixel::RGBA8888);
 
-  mImpl->loaderInfo.animated.currentFrame = 1 + ( frameIndex % mImpl->loaderInfo.animated.frameCount );
-  ReadNextFrame( mImpl->loaderInfo, mImpl->imageProperties, pixelBuffer.GetBuffer(), &error );
+  mImpl->loaderInfo.animated.currentFrame = 1 + (frameIndex % mImpl->loaderInfo.animated.frameCount);
+  ReadNextFrame(mImpl->loaderInfo, mImpl->imageProperties, pixelBuffer.GetBuffer(), &error);
 
-  if( error != 0 )
+  if(error != 0)
   {
     pixelBuffer = Dali::Devel::PixelBuffer();
   }
@@ -1305,7 +1342,7 @@ Dali::Devel::PixelBuffer GifLoading::LoadFrame( uint32_t frameIndex )
 
 ImageDimensions GifLoading::GetImageSize() const
 {
-  return ImageDimensions( mImpl->imageProperties.w, mImpl->imageProperties.h );
+  return ImageDimensions(mImpl->imageProperties.w, mImpl->imageProperties.h);
 }
 
 uint32_t GifLoading::GetImageCount() const
@@ -1313,7 +1350,7 @@ uint32_t GifLoading::GetImageCount() const
   return mImpl->loaderInfo.animated.frameCount;
 }
 
-uint32_t GifLoading::GetFrameInterval( uint32_t frameIndex ) const
+uint32_t GifLoading::GetFrameInterval(uint32_t frameIndex) const
 {
   return mImpl->loaderInfo.animated.frames[frameIndex].info.delay * 10;
 }
@@ -1323,8 +1360,13 @@ std::string GifLoading::GetUrl() const
   return mImpl->mUrl;
 }
 
+bool GifLoading::HasLoadingSucceeded() const
+{
+  return mImpl->mLoadSucceeded;
+}
+
 } // namespace Adaptor
 
 } // namespace Internal
 
-} // namespace Dali
\ No newline at end of file
+} // namespace Dali