Fix a crash when the same image is set repeatedly
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / npatch-loader.cpp
index 026450d..f23f1ca 100644 (file)
@@ -21,6 +21,7 @@
 // EXTERNAL HEADER
 #include <dali/devel-api/common/hash.h>
 #include <dali/devel-api/images/texture-set-image.h>
+#include <dali-toolkit/public-api/image-loader/sync-image-loader.h>
 
 namespace Dali
 {
@@ -39,11 +40,13 @@ NPatchLoader::~NPatchLoader()
 {
 }
 
-std::size_t NPatchLoader::Load( const std::string& url )
+std::size_t NPatchLoader::Load( const std::string& url, const Rect< int >& border )
 {
   std::size_t hash = CalculateHash( url );
   OwnerContainer< Data* >::SizeType index = UNINITIALIZED_ID;
   const OwnerContainer< Data* >::SizeType count = mCache.Count();
+  int cachedIndex = -1;
+
   for( ; index < count; ++index )
   {
     if( mCache[ index ]->hash == hash )
@@ -51,31 +54,104 @@ std::size_t NPatchLoader::Load( const std::string& url )
       // hash match, check url as well in case of hash collision
       if( mCache[ index ]->url == url )
       {
-        return index+1u; // valid indices are from 1 onwards
+        // Use cached data
+        if( mCache[ index ]->border == border )
+        {
+          return index+1u; // valid indices are from 1 onwards
+        }
+        else
+        {
+          cachedIndex = index;
+        }
       }
     }
   }
-  // got to the end so no match, decode N patch and append new item to cache
-  NinePatchImage ninePatch = NinePatchImage::New( url );
-  if( ninePatch )
+
+  if( cachedIndex != -1 )
   {
+    // Same url but border is different - use the existing texture
     Data* data = new Data();
     data->hash = hash;
     data->url = url;
-    BufferImage croppedImage = ninePatch.CreateCroppedBufferImage();
-    if( croppedImage )
+    data->croppedWidth = mCache[ cachedIndex ]->croppedWidth;
+    data->croppedHeight = mCache[ cachedIndex ]->croppedHeight;
+
+    data->textureSet = mCache[ cachedIndex ]->textureSet;
+
+    NinePatchImage::StretchRanges stretchRangesX;
+    stretchRangesX.PushBack( Uint16Pair( border.left, data->croppedWidth - border.right ) );
+
+    NinePatchImage::StretchRanges stretchRangesY;
+    stretchRangesY.PushBack( Uint16Pair( border.top, data->croppedHeight - border.bottom ) );
+
+    data->stretchPixelsX = stretchRangesX;
+    data->stretchPixelsY = stretchRangesY;
+    data->border = border;
+
+    mCache.PushBack( data );
+
+    return mCache.Count(); // valid ids start from 1u
+  }
+
+  // got to the end so no match, decode N patch and append new item to cache
+  if( border == Rect< int >( 0, 0, 0, 0 ) )
+  {
+    NinePatchImage ninePatch = NinePatchImage::New( url );
+    if( ninePatch )
     {
+      BufferImage croppedImage = ninePatch.CreateCroppedBufferImage();
+      if( croppedImage )
+      {
+        Data* data = new Data();
+        data->hash = hash;
+        data->url = url;
+        data->textureSet = TextureSet::New();
+        TextureSetImage( data->textureSet, 0u, croppedImage );
+        data->croppedWidth = croppedImage.GetWidth();
+        data->croppedHeight = croppedImage.GetHeight();
+        data->stretchPixelsX = ninePatch.GetStretchPixelsX();
+        data->stretchPixelsY = ninePatch.GetStretchPixelsY();
+        data->border = Rect< int >( 0, 0, 0, 0 );
+        mCache.PushBack( data );
+
+        return mCache.Count(); // valid ids start from 1u
+      }
+    }
+  }
+  else
+  {
+    // Load image from file
+    PixelData pixels = SyncImageLoader::Load( url );
+    if( pixels )
+    {
+      Data* data = new Data();
+      data->hash = hash;
+      data->url = url;
+      data->croppedWidth = pixels.GetWidth();
+      data->croppedHeight = pixels.GetHeight();
+
+      Texture texture = Texture::New( TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight() );
+      texture.Upload( pixels, 0, 0, 0, 0, pixels.GetWidth(), pixels.GetHeight() );
+
       data->textureSet = TextureSet::New();
-      TextureSetImage( data->textureSet, 0u, croppedImage );
-      data->croppedWidth = croppedImage.GetWidth();
-      data->croppedHeight = croppedImage.GetHeight();
-      data->stretchPixelsX = ninePatch.GetStretchPixelsX();
-      data->stretchPixelsY = ninePatch.GetStretchPixelsY();
+      data->textureSet.SetTexture( 0u, texture );
+
+      NinePatchImage::StretchRanges stretchRangesX;
+      stretchRangesX.PushBack( Uint16Pair( border.left, data->croppedWidth - border.right ) );
+
+      NinePatchImage::StretchRanges stretchRangesY;
+      stretchRangesY.PushBack( Uint16Pair( border.top, data->croppedHeight - border.bottom ) );
+
+      data->stretchPixelsX = stretchRangesX;
+      data->stretchPixelsY = stretchRangesY;
+      data->border = border;
+
       mCache.PushBack( data );
 
       return mCache.Count(); // valid ids start from 1u
     }
   }
+
   return 0u;
 }