(Vector) Support EncodedImageBuffer can use for vector image 97/300597/10
authorEunki Hong <eunkiki.hong@samsung.com>
Sat, 28 Oct 2023 16:17:50 +0000 (01:17 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Mon, 6 Nov 2023 02:33:50 +0000 (02:33 +0000)
Support to append extension when we use imagetype

For example, if EncodedImageBuffer has VECTOR_IMAGE type, we will generate url
"enbuf://3.svg" So we can use it directly by ImageView -> SvgVisual

And also, let we support Remote animated vector image.
(Since we can load animated vector image by raw buffer.)

Change-Id: I09fd214021507cd8d29bbd3c3720d4427f5eedd7
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
15 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-VisualUrl.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.h
automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp
dali-toolkit/internal/image-loader/loading-task.cpp
dali-toolkit/internal/texture-manager/texture-cache-manager.cpp
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h
dali-toolkit/internal/visuals/svg/svg-task.cpp
dali-toolkit/internal/visuals/svg/svg-task.h
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/visual-url.cpp
dali-toolkit/internal/visuals/visual-url.h

index 3e9a117..f9df7d8 100644 (file)
@@ -62,6 +62,9 @@ const char* TEST_IMAGE_3_FILE_NAME = TEST_RESOURCE_DIR "/icon-edit.png";
 const char* TEST_IMAGE_4_FILE_NAME = TEST_RESOURCE_DIR "/application-icon-20.png";
 const char* TEST_MASK_FILE_NAME    = TEST_RESOURCE_DIR "/mask.png";
 
+const char* TEST_SVG_FILE_NAME                   = TEST_RESOURCE_DIR "/svg1.svg";
+const char* TEST_ANIMATED_VECTOR_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/insta_camera.json";
+
 class TestObserver : public Dali::Toolkit::TextureUploadObserver
 {
 public:
@@ -258,7 +261,7 @@ int UtcTextureManagerEncodedImageBuffer(void)
 
   std::string url1 = textureManager.AddEncodedImageBuffer(buffer1);
   std::string url2 = textureManager.AddEncodedImageBuffer(buffer1);
-  std::string url3 = VisualUrl::CreateBufferUrl(""); ///< Impossible Buffer URL. for coverage
+  std::string url3 = VisualUrl::CreateBufferUrl("", ""); ///< Impossible Buffer URL. for coverage
 
   // Check if same EncodedImageBuffer get same url
   DALI_TEST_CHECK(url1 == url2);
@@ -437,6 +440,72 @@ int UtcTextureManagerEncodedImageBuffer(void)
   END_TEST;
 }
 
+int UtcTextureManagerEncodedImageBufferWithImageType(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcTextureManagerEncodedImageBufferWithImageType");
+
+  auto  visualFactory  = Toolkit::VisualFactory::Get();
+  auto& textureManager = GetImplementation(visualFactory).GetTextureManager(); // Use VisualFactory's texture manager
+
+  // Get encoded raw-buffer image and generate url
+  EncodedImageBuffer buffer1 = ConvertFileToEncodedImageBuffer(TEST_SVG_FILE_NAME);
+  EncodedImageBuffer buffer2 = ConvertFileToEncodedImageBuffer(TEST_ANIMATED_VECTOR_IMAGE_FILE_NAME);
+
+  std::string url1 = textureManager.AddEncodedImageBuffer(buffer1);
+  std::string url2 = textureManager.AddEncodedImageBuffer(buffer1);
+
+  // Check if same EncodedImageBuffer get same url
+  DALI_TEST_CHECK(url1 == url2);
+  // Reduce reference count
+  textureManager.RemoveEncodedImageBuffer(url1);
+  // Check whethere url1 still valid
+  DALI_TEST_CHECK(textureManager.GetEncodedImageBuffer(url1));
+
+  url2 = textureManager.AddEncodedImageBuffer(buffer2);
+  // Check if difference EncodedImageBuffer get difference url
+  DALI_TEST_CHECK(url1 != url2);
+
+  buffer1.SetImageType(EncodedImageBuffer::ImageType::VECTOR_IMAGE);
+  buffer2.SetImageType(EncodedImageBuffer::ImageType::ANIMATED_VECTOR_IMAGE);
+
+  std::string url1AfterType = textureManager.AddEncodedImageBuffer(buffer1);
+  std::string url2AfterType = textureManager.AddEncodedImageBuffer(buffer2);
+
+  // Check if EncodedImageBuffer with imagetype get difference url.
+  DALI_TEST_CHECK(url1 != url1AfterType);
+  DALI_TEST_CHECK(url2 != url2AfterType);
+  DALI_TEST_CHECK(url1AfterType != url2AfterType);
+
+  int  bufferId      = std::atoi(VisualUrl::GetLocationWithoutExtension(url1AfterType).c_str());
+  auto urlFromBuffer = textureManager.GetVisualUrl(bufferId);
+
+  // Check url from buffer id is equal with what we know.
+  DALI_TEST_CHECK(url1AfterType == urlFromBuffer.GetUrl());
+
+  // Reduce reference count
+  textureManager.RemoveEncodedImageBuffer(url1AfterType);
+  // Check whethere url1 still valid
+  DALI_TEST_CHECK(textureManager.GetEncodedImageBuffer(url1AfterType));
+
+  // Reduce reference count
+  textureManager.RemoveEncodedImageBuffer(url1AfterType);
+  // Check whethere url1 is invalid
+  DALI_TEST_CHECK(!textureManager.GetEncodedImageBuffer(url1AfterType));
+
+  // Reduce reference count
+  textureManager.RemoveEncodedImageBuffer(url2);
+  // Check whethere url2 is still valid
+  DALI_TEST_CHECK(textureManager.GetEncodedImageBuffer(url2));
+
+  // Reduce reference count
+  textureManager.RemoveEncodedImageBuffer(url2);
+  // Check whethere url2 is invalid
+  DALI_TEST_CHECK(!textureManager.GetEncodedImageBuffer(url2));
+
+  END_TEST;
+}
+
 int UtcTextureManagerExternalTexture(void)
 {
   ToolkitTestApplication application;
index 3003ae4..3e5e8eb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -418,6 +418,19 @@ int UtcDaliVisualUrlGetLocationP(void)
   END_TEST;
 }
 
+int UtcDaliVisualUrlGetLocationWithoutExtensionP(void)
+{
+  tet_infoline("UtcDaliVisualUrl GetLocationWithoutExtension Positive");
+
+  DALI_TEST_EQUAL("a", VisualUrl("http://a.png").GetLocationWithoutExtension());
+  DALI_TEST_EQUAL("1", VisualUrl("dali://1.jpg").GetLocationWithoutExtension());
+  DALI_TEST_EQUAL("4", VisualUrl("enbuf://4.svg").GetLocationWithoutExtension());
+  DALI_TEST_EQUAL("", VisualUrl("ftp://.png").GetLocationWithoutExtension());
+  DALI_TEST_EQUAL("http://a.jpg", VisualUrl("http://http://a.jpg.jpg").GetLocationWithoutExtension());
+
+  END_TEST;
+}
+
 int UtcDaliVisualUrlGetLocationN(void)
 {
   tet_infoline("UtcDaliVisualUrl GetLocation Negative");
@@ -432,6 +445,20 @@ int UtcDaliVisualUrlGetLocationN(void)
   END_TEST;
 }
 
+int UtcDaliVisualUrlGetLocationWithoutExtensionN(void)
+{
+  tet_infoline("UtcDaliVisualUrl GetLocationWithoutExtension Negative");
+
+  DALI_TEST_EQUAL("", VisualUrl("").GetLocationWithoutExtension());
+  DALI_TEST_EQUAL("a", VisualUrl("a").GetLocationWithoutExtension());
+  DALI_TEST_EQUAL("dali:/1.jpg", VisualUrl("dali:/1.jpg").GetLocationWithoutExtension());
+  DALI_TEST_EQUAL("dali//1.jpg", VisualUrl("dali//1.jpg").GetLocationWithoutExtension());
+  DALI_TEST_EQUAL("enbuf:/2.png", VisualUrl("enbuf:/2.png").GetLocationWithoutExtension());
+  DALI_TEST_EQUAL("a.jpg", VisualUrl("http:/http://a.jpg.jpngif").GetLocationWithoutExtension());
+
+  END_TEST;
+}
+
 int UtcDaliVisualUrlCreateTextureUrl(void)
 {
   tet_infoline("UtcDaliVisualUrl CreateTextureUrl");
@@ -447,9 +474,20 @@ int UtcDaliVisualUrlCreateBufferUrl(void)
 {
   tet_infoline("UtcDaliVisualUrl CreateBufferUrl");
 
-  DALI_TEST_EQUAL("enbuf://a", VisualUrl::CreateBufferUrl("a"));
-  DALI_TEST_EQUAL("enbuf://1234", VisualUrl::CreateBufferUrl("1234"));
-  DALI_TEST_EQUAL("enbuf://", VisualUrl::CreateBufferUrl(""));
+  DALI_TEST_EQUAL("enbuf://a", VisualUrl::CreateBufferUrl("a", ""));
+  DALI_TEST_EQUAL("enbuf://1234", VisualUrl::CreateBufferUrl("1234", ""));
+  DALI_TEST_EQUAL("enbuf://", VisualUrl::CreateBufferUrl("", ""));
+
+  END_TEST;
+}
+
+int UtcDaliVisualUrlCreateBufferUrlWithExtension(void)
+{
+  tet_infoline("UtcDaliVisualUrl CreateBufferUrl with extension");
+
+  DALI_TEST_EQUAL("enbuf://a.jpg", VisualUrl::CreateBufferUrl("a", ".jpg"));
+  DALI_TEST_EQUAL("enbuf://1234567", VisualUrl::CreateBufferUrl("1234", "567"));
+  DALI_TEST_EQUAL("enbuf://b", VisualUrl::CreateBufferUrl("", "b"));
 
   END_TEST;
 }
index ef389ed..600a866 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
 
 namespace Dali
 {
-EncodedImageBuffer ConvertFileToEncodedImageBuffer(const char* url)
+EncodedImageBuffer ConvertFileToEncodedImageBuffer(const char* url, EncodedImageBuffer::ImageType imageType)
 {
   EncodedImageBuffer buffer;
-  FILE *fp;
+  FILE*              fp;
   fp = fopen(url, "rb");
   if(fp != NULL)
   {
     fseek(fp, 0, SEEK_END);
-    size_t size = ftell(fp);
+    size_t                size = ftell(fp);
     Dali::Vector<uint8_t> data;
     data.Resize(size);
     fseek(fp, 0, SEEK_SET);
     size_t realSize = fread(data.Begin(), sizeof(uint8_t), size, fp);
     fclose(fp);
     data.Resize(realSize);
-    buffer = EncodedImageBuffer::New(data);
+    buffer = EncodedImageBuffer::New(data, imageType);
   }
   return buffer;
 }
index 96fbe46..3b6e28b 100644 (file)
@@ -2,7 +2,7 @@
 #define TEST_ENCODED_IMAGE_BUFFER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -23,9 +23,8 @@
 
 namespace Dali
 {
-
 // util function to convert local file to EncodedImageBuffer
-EncodedImageBuffer ConvertFileToEncodedImageBuffer(const char* url);
+EncodedImageBuffer ConvertFileToEncodedImageBuffer(const char* url, EncodedImageBuffer::ImageType imageType = EncodedImageBuffer::ImageType::DEFAULT);
 
 } // namespace Dali
 
index 2f2901f..0a82fb4 100644 (file)
@@ -879,6 +879,86 @@ int UtcDaliImageViewSyncLoadingEncodedBuffer(void)
   END_TEST;
 }
 
+int UtcDaliImageViewEncodedBufferWithSvg(void)
+{
+  ToolkitTestApplication     application;
+  TestGlAbstraction&         gl          = application.GetGlAbstraction();
+  const std::vector<GLuint>& textures    = gl.GetBoundTextures();
+  size_t                     numTextures = textures.size();
+
+  // Get encoded raw-buffer svg image and generate url
+  EncodedImageBuffer buffer = ConvertFileToEncodedImageBuffer(TEST_SVG_FILE_NAME, EncodedImageBuffer::ImageType::VECTOR_IMAGE);
+  ImageUrl           url    = Toolkit::Image::GenerateUrl(buffer);
+
+  // Async loading, no atlasing for big size image
+  ImageView imageView = ImageView::New(url.GetUrl());
+
+  // By default, Aysnc loading is used
+  application.GetScene().Add(imageView);
+  imageView.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
+  imageView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  application.SendNotification();
+  application.Render(16);
+
+  // Load svg image + rasterize.
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+
+  const std::vector<GLuint>& textures2 = gl.GetBoundTextures();
+  DALI_TEST_GREATER(textures2.size(), numTextures, TEST_LOCATION);
+
+  // Remove visual, for line coverage.
+  imageView.Unparent();
+  application.SendNotification();
+  application.Render(16);
+
+  END_TEST;
+}
+
+int UtcDaliImageViewEncodedBufferWithAnimatedVectorImage(void)
+{
+  ToolkitTestApplication     application;
+  TestGlAbstraction&         gl          = application.GetGlAbstraction();
+  const std::vector<GLuint>& textures    = gl.GetBoundTextures();
+  size_t                     numTextures = textures.size();
+
+  // Get encoded raw-buffer lottie image and generate url
+  EncodedImageBuffer buffer = ConvertFileToEncodedImageBuffer(TEST_ANIMATED_VECTOR_IMAGE_FILE_NAME, EncodedImageBuffer::ImageType::ANIMATED_VECTOR_IMAGE);
+  ImageUrl           url    = Toolkit::Image::GenerateUrl(buffer);
+
+  // Async loading, no atlasing for big size image
+  ImageView imageView = ImageView::New(url.GetUrl());
+
+  // By default, Aysnc loading is used
+  application.GetScene().Add(imageView);
+  imageView.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
+  imageView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  application.SendNotification();
+  application.Render(16);
+
+  // Load lottie image is sync. Only wait rasterize.
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+
+  const std::vector<GLuint>& textures2 = gl.GetBoundTextures();
+  DALI_TEST_GREATER(textures2.size(), numTextures, TEST_LOCATION);
+
+  // Remove visual, for line coverage.
+  imageView.Unparent();
+  application.SendNotification();
+  application.Render(16);
+
+  END_TEST;
+}
+
 int UtcDaliImageViewAddedTexture(void)
 {
   ToolkitTestApplication application;
@@ -2789,6 +2869,34 @@ int UtcDaliImageViewLoadRemoteSVG(void)
   END_TEST;
 }
 
+int UtcDaliImageViewLoadRemoteLottie(void)
+{
+  tet_infoline("Test load from a remote server. (Note we don't support real download now. Just for line coverage)");
+
+  ToolkitTestApplication application;
+
+  {
+    Toolkit::ImageView imageView;
+    imageView = Toolkit::ImageView::New();
+    imageView.SetImage("https://lottie.json");
+    imageView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+    imageView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+    imageView.SetProperty(Actor::Property::SIZE, Vector2(300, 300));
+    imageView.SetProperty(Actor::Property::POSITION, Vector3(150.0f, 150.0f, 0.0f));
+
+    application.GetScene().Add(imageView);
+
+    DALI_TEST_CHECK(imageView);
+
+    application.SendNotification();
+    application.Render();
+
+    // Do not check anything for here.
+  }
+
+  END_TEST;
+}
+
 int UtcDaliImageViewSyncSVGLoading(void)
 {
   ToolkitTestApplication application;
index 74788cb..2c08799 100644 (file)
@@ -215,6 +215,9 @@ void LoadingTask::Load()
   else if(encodedImageBuffer)
   {
     pixelBuffer = Dali::LoadImageFromBuffer(encodedImageBuffer.GetRawBuffer(), dimensions, fittingMode, samplingMode, orientationCorrection);
+
+    // We don't need to hold image buffer anymore.
+    encodedImageBuffer.Reset();
   }
   else if(url.IsValid() && url.IsLocalResource())
   {
index fc77c6f..4343a84 100644 (file)
@@ -21,6 +21,8 @@
 // EXTERNAL HEADERS
 #include <dali/devel-api/common/hash.h>
 #include <dali/integration-api/debug.h>
+#include <string_view>
+#include <unordered_map>
 
 // INTERNAL HEADERS
 
@@ -30,6 +32,24 @@ namespace Toolkit
 {
 namespace Internal
 {
+namespace
+{
+const std::string_view& GetEncodedImageBufferExtensions(Dali::EncodedImageBuffer::ImageType imageType)
+{
+  static const std::unordered_map<Dali::EncodedImageBuffer::ImageType, const std::string_view> gEncodedImageBufferExtensionMap =
+    {
+      {Dali::EncodedImageBuffer::ImageType::REGULAR_IMAGE, ""},
+      {Dali::EncodedImageBuffer::ImageType::VECTOR_IMAGE, ".svg"},
+      {Dali::EncodedImageBuffer::ImageType::ANIMATED_VECTOR_IMAGE, ".json"},
+    };
+
+  const auto iter = gEncodedImageBufferExtensionMap.find(imageType);
+
+  DALI_ASSERT_DEBUG(iter != gEncodedImageBufferExtensionMap.end());
+
+  return iter->second;
+}
+} // namespace
 #ifdef DEBUG_ENABLED
 extern Debug::Filter* gTextureManagerLogFilter; ///< Define at texture-manager-impl.cpp
 
@@ -116,7 +136,10 @@ VisualUrl TextureCacheManager::GetVisualUrl(const TextureCacheManager::TextureId
     case TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_BUFFER:
     {
       DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::GetVisualUrl. Using cached buffer index=%d, bufferId=%d\n", cacheIndex.GetIndex(), textureId);
-      visualUrl = VisualUrl::CreateBufferUrl(std::to_string(textureId));
+
+      EncodedImageBufferInfo& cachedEncodedImageBufferInfo(mEncodedImageBuffers[cacheIndex.GetIndex()]);
+      const auto&             encodedImageBuffer = cachedEncodedImageBufferInfo.encodedImageBuffer;
+      visualUrl                                  = VisualUrl::CreateBufferUrl(std::to_string(textureId), GetEncodedImageBufferExtensions(encodedImageBuffer.GetImageType()));
       break;
     }
     default:
@@ -217,7 +240,7 @@ EncodedImageBuffer TextureCacheManager::GetEncodedImageBuffer(const VisualUrl& u
   EncodedImageBuffer encodedImageBuffer; // empty handle
   if(url.IsValid() && VisualUrl::BUFFER == url.GetProtocolType())
   {
-    std::string location = url.GetLocation();
+    std::string location = url.GetLocationWithoutExtension();
     if(location.size() > 0u)
     {
       TextureId bufferId = std::stoi(location);
@@ -252,7 +275,7 @@ std::string TextureCacheManager::AddEncodedImageBuffer(const EncodedImageBuffer&
 
     // If same buffer added, increase reference count and return.
     bufferInfo.referenceCount++;
-    return VisualUrl::CreateBufferUrl(std::to_string(bufferInfo.bufferId));
+    return VisualUrl::CreateBufferUrl(std::to_string(bufferInfo.bufferId), GetEncodedImageBufferExtensions(encodedImageBuffer.GetImageType()));
   }
 
   TextureId bufferId = GenerateTextureId(TextureCacheIndex(TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_BUFFER, mEncodedImageBuffers.size()));
@@ -268,7 +291,7 @@ std::string TextureCacheManager::AddEncodedImageBuffer(const EncodedImageBuffer&
 
   DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::AddExternalEncodedImageBuffer() : New buffer regested. bufferId:%d\n", info.bufferId);
 
-  return VisualUrl::CreateBufferUrl(std::to_string(info.bufferId));
+  return VisualUrl::CreateBufferUrl(std::to_string(info.bufferId), GetEncodedImageBufferExtensions(encodedImageBuffer.GetImageType()));
 }
 
 TextureSet TextureCacheManager::RemoveExternalTexture(const VisualUrl& url)
@@ -321,7 +344,7 @@ EncodedImageBuffer TextureCacheManager::RemoveEncodedImageBuffer(const VisualUrl
     if(VisualUrl::BUFFER == url.GetProtocolType())
     {
       // get the location from the Url
-      std::string location = url.GetLocation();
+      std::string location = url.GetLocationWithoutExtension();
       if(location.size() > 0u)
       {
         TextureId bufferId = std::stoi(location);
@@ -376,7 +399,7 @@ void TextureCacheManager::UseExternalResource(const VisualUrl& url)
   }
   else if(VisualUrl::BUFFER == url.GetProtocolType())
   {
-    std::string location = url.GetLocation();
+    std::string location = url.GetLocationWithoutExtension();
     if(location.size() > 0u)
     {
       TextureId         id         = std::stoi(location);
index 982d6dd..09c4418 100644 (file)
@@ -113,6 +113,12 @@ AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
 {
   if(!mCoreShutdown)
   {
+    if(mImageUrl.IsBufferResource())
+    {
+      TextureManager& textureManager = mFactoryCache.GetTextureManager();
+      textureManager.RemoveEncodedImageBuffer(mImageUrl.GetUrl());
+    }
+
     auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
     vectorAnimationManager.RemoveObserver(*this);
 
@@ -380,7 +386,20 @@ void AnimatedVectorImageVisual::OnInitialize(void)
   mVectorAnimationTask->ResourceReadySignal().Connect(this, &AnimatedVectorImageVisual::OnResourceReady);
   mVectorAnimationTask->SetAnimationFinishedCallback(MakeCallback(this, &AnimatedVectorImageVisual::OnAnimationFinished));
 
-  mVectorAnimationTask->RequestLoad(mImageUrl, IsSynchronousLoadingRequired());
+  EncodedImageBuffer encodedImageBuffer;
+
+  if(mImageUrl.IsBufferResource())
+  {
+    // Increase reference count of External Resources :
+    // EncodedImageBuffer.
+    // Reference count will be decreased at destructor of the visual.
+    TextureManager& textureManager = mFactoryCache.GetTextureManager();
+    textureManager.UseExternalResource(mImageUrl.GetUrl());
+
+    encodedImageBuffer = textureManager.GetEncodedImageBuffer(mImageUrl.GetUrl());
+  }
+
+  mVectorAnimationTask->RequestLoad(mImageUrl, encodedImageBuffer, IsSynchronousLoadingRequired());
 
   auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
   vectorAnimationManager.AddObserver(*this);
index d7f14ba..c1e9d56 100644 (file)
@@ -19,6 +19,7 @@
 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h>
 
 // EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/file-loader.h>
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/trace.h>
 #include <dali/public-api/math/math-utils.h>
@@ -55,6 +56,7 @@ DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_IMAGE_PERFORMANCE_MARKER, false)
 VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache)
 : AsyncTask(MakeCallback(this, &VectorAnimationTask::TaskCompleted), AsyncTask::PriorityType::HIGH, AsyncTask::ThreadType::WORKER_THREAD),
   mImageUrl(),
+  mEncodedImageBuffer(),
   mVectorRenderer(VectorAnimationRenderer::New()),
   mAnimationData(),
   mVectorAnimationThread(factoryCache.GetVectorAnimationManager().GetVectorAnimationThread()),
@@ -153,14 +155,36 @@ bool VectorAnimationTask::Load(bool synchronousLoading)
   }
 #endif
 
-  if(!mVectorRenderer.Load(mImageUrl.GetUrl()))
+  if(mEncodedImageBuffer)
   {
-    DALI_LOG_ERROR("VectorAnimationTask::Load: Load failed [%s]\n", mImageUrl.GetUrl().c_str());
-    mLoadFailed = true;
+    if(!mVectorRenderer.Load(mEncodedImageBuffer.GetRawBuffer()))
+    {
+      mLoadFailed = true;
+    }
+
+    // We don't need to hold image buffer anymore.
+    mEncodedImageBuffer.Reset();
+  }
+  else if(mImageUrl.IsLocalResource())
+  {
+    if(!mVectorRenderer.Load(mImageUrl.GetUrl()))
+    {
+      mLoadFailed = true;
+    }
+  }
+  else
+  {
+    Dali::Vector<uint8_t> remoteData;
+    if(!Dali::FileLoader::DownloadFileSynchronously(mImageUrl.GetUrl(), remoteData) || // Failed if we fail to download json file,
+       !mVectorRenderer.Load(remoteData))                                              // or download data is not valid vector animation file.
+    {
+      mLoadFailed = true;
+    }
   }
 
   if(mLoadFailed)
   {
+    DALI_LOG_ERROR("VectorAnimationTask::Load: Load failed [%s]\n", mImageUrl.GetUrl().c_str());
     mLoadRequest = false;
     if(!synchronousLoading && mLoadCompletedCallback)
     {
@@ -215,9 +239,10 @@ void VectorAnimationTask::SetRenderer(Renderer renderer)
   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetRenderer [%p]\n", this);
 }
 
-void VectorAnimationTask::RequestLoad(const VisualUrl& url, bool synchronousLoading)
+void VectorAnimationTask::RequestLoad(const VisualUrl& url, EncodedImageBuffer encodedImageBuffer, bool synchronousLoading)
 {
-  mImageUrl = url;
+  mImageUrl           = url;
+  mEncodedImageBuffer = encodedImageBuffer;
 
   if(!synchronousLoading)
   {
index c3ac749..123d685 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali/devel-api/adaptor-framework/vector-animation-renderer.h>
 #include <dali/devel-api/threading/conditional-wait.h>
 #include <dali/public-api/adaptor-framework/async-task-manager.h>
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 #include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/object/property-array.h>
 #include <chrono>
@@ -162,9 +163,10 @@ public:
    * @brief Requests to load the animation file.
    *
    * @param[in] url The url of the vector animation file
+   * @param[in] encodedImageBuffer The resource buffer if required.
    * @param[in] synchronousLoading True if the url should be loaded synchronously
    */
-  void RequestLoad(const VisualUrl& url, bool synchronousLoading);
+  void RequestLoad(const VisualUrl& url, EncodedImageBuffer encodedImageBuffer, bool synchronousLoading);
 
   /**
    * @brief Queries whether loading is requested.
@@ -357,6 +359,7 @@ private:
   };
 
   VisualUrl                            mImageUrl;
+  EncodedImageBuffer                   mEncodedImageBuffer;
   VectorAnimationRenderer              mVectorRenderer;
   std::vector<AnimationData>           mAnimationData[2];
   VectorAnimationThread&               mVectorAnimationThread;
index de551d6..5f8ed8c 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 // CLASS HEADER
-#include "svg-task.h"
+#include <dali-toolkit/internal/visuals/svg/svg-task.h>
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/file-loader.h>
@@ -64,9 +64,10 @@ VectorImageRenderer SvgTask::GetRenderer()
   return mVectorRenderer;
 }
 
-SvgLoadingTask::SvgLoadingTask(VectorImageRenderer vectorRenderer, const VisualUrl& url, float dpi, CallbackBase* callback)
+SvgLoadingTask::SvgLoadingTask(VectorImageRenderer vectorRenderer, const VisualUrl& url, EncodedImageBuffer encodedImageBuffer, float dpi, CallbackBase* callback)
 : SvgTask(vectorRenderer, callback, url.GetProtocolType() == VisualUrl::ProtocolType::REMOTE ? AsyncTask::PriorityType::LOW : AsyncTask::PriorityType::HIGH),
   mImageUrl(url),
+  mEncodedImageBuffer(encodedImageBuffer),
   mDpi(dpi)
 {
 }
@@ -98,25 +99,35 @@ void SvgLoadingTask::Process()
 
   Dali::Vector<uint8_t> buffer;
 
-  if(!mImageUrl.IsLocalResource())
+  if(mEncodedImageBuffer)
   {
-    if(!Dali::FileLoader::DownloadFileSynchronously(mImageUrl.GetUrl(), buffer))
+    // Copy raw buffer.
+    // TODO : Can't we load svg without copy buffer in future?
+    buffer = mEncodedImageBuffer.GetRawBuffer();
+
+    // We don't need to hold image buffer anymore.
+    mEncodedImageBuffer.Reset();
+  }
+  else if(mImageUrl.IsLocalResource())
+  {
+    if(!Dali::FileLoader::ReadFile(mImageUrl.GetUrl(), buffer))
     {
-      DALI_LOG_ERROR("Failed to download file! [%s]\n", mImageUrl.GetUrl().c_str());
+      DALI_LOG_ERROR("Failed to read file! [%s]\n", mImageUrl.GetUrl().c_str());
       loadFailed = true;
     }
   }
   else
   {
-    if(!Dali::FileLoader::ReadFile(mImageUrl.GetUrl(), buffer))
+    if(!Dali::FileLoader::DownloadFileSynchronously(mImageUrl.GetUrl(), buffer))
     {
-      DALI_LOG_ERROR("Failed to read file! [%s]\n", mImageUrl.GetUrl().c_str());
+      DALI_LOG_ERROR("Failed to download file! [%s]\n", mImageUrl.GetUrl().c_str());
       loadFailed = true;
     }
   }
 
   if(!loadFailed)
   {
+    buffer.Reserve(buffer.Count() + 1u);
     buffer.PushBack('\0');
 
     if(!mVectorRenderer.Load(buffer, mDpi))
index beeaee4..8b421d4 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali/public-api/common/intrusive-ptr.h>
 #include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/images/pixel-data.h>
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 #include <memory>
 
 // INTERNAL INCLUDES
@@ -112,10 +113,11 @@ public:
    * Constructor
    * @param[in] vectorRenderer The vector rasterizer.
    * @param[in] url The URL to svg resource to use.
+   * @param[in] encodedImageBuffer The resource buffer if required.
    * @param[in] dpi The DPI of the screen.
    * @param[in] callback The callback that is called when the operation is completed.
    */
-  SvgLoadingTask(VectorImageRenderer vectorRenderer, const VisualUrl& url, float dpi, CallbackBase* callback);
+  SvgLoadingTask(VectorImageRenderer vectorRenderer, const VisualUrl& url, EncodedImageBuffer encodedImageBuffer, float dpi, CallbackBase* callback);
 
   /**
    * Destructor.
@@ -141,8 +143,9 @@ private:
   SvgLoadingTask& operator=(const SvgLoadingTask& task) = delete;
 
 private:
-  VisualUrl mImageUrl;
-  float     mDpi;
+  VisualUrl          mImageUrl;
+  EncodedImageBuffer mEncodedImageBuffer;
+  float              mDpi;
 };
 
 class SvgRasterizingTask : public SvgTask
index 33b7781..8d64c8f 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 // CLASS HEADER
-#include "svg-visual.h"
+#include <dali-toolkit/internal/visuals/svg/svg-visual.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
@@ -92,6 +92,12 @@ SvgVisual::~SvgVisual()
     {
       Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
     }
+
+    if(mImageUrl.IsBufferResource())
+    {
+      TextureManager& textureManager = mFactoryCache.GetTextureManager();
+      textureManager.RemoveEncodedImageBuffer(mImageUrl.GetUrl());
+    }
   }
 }
 
@@ -105,9 +111,22 @@ void SvgVisual::OnInitialize()
   Vector2 dpi     = Stage::GetCurrent().GetDpi();
   float   meanDpi = (dpi.height + dpi.width) * 0.5f;
 
-  mLoadingTask = new SvgLoadingTask(mVectorRenderer, mImageUrl, meanDpi, MakeCallback(this, &SvgVisual::ApplyRasterizedImage));
+  EncodedImageBuffer encodedImageBuffer;
+
+  if(mImageUrl.IsBufferResource())
+  {
+    // Increase reference count of External Resources :
+    // EncodedImageBuffer.
+    // Reference count will be decreased at destructor of the visual.
+    TextureManager& textureManager = mFactoryCache.GetTextureManager();
+    textureManager.UseExternalResource(mImageUrl.GetUrl());
+
+    encodedImageBuffer = textureManager.GetEncodedImageBuffer(mImageUrl.GetUrl());
+  }
+
+  mLoadingTask = new SvgLoadingTask(mVectorRenderer, mImageUrl, encodedImageBuffer, meanDpi, MakeCallback(this, &SvgVisual::ApplyRasterizedImage));
 
-  if(IsSynchronousLoadingRequired() && mImageUrl.IsLocalResource())
+  if(IsSynchronousLoadingRequired() && (mImageUrl.IsLocalResource() || mImageUrl.IsBufferResource()))
   {
     mLoadingTask->Process();
     if(!mLoadingTask->HasSucceeded())
index fc19714..93c1e78 100644 (file)
@@ -233,9 +233,9 @@ VisualUrl::VisualUrl(const std::string& url)
   if(!url.empty())
   {
     mLocation = ResolveLocation(url);
-    if(VisualUrl::TEXTURE != mLocation && VisualUrl::BUFFER != mLocation)
+    if(VisualUrl::TEXTURE != mLocation)
     {
-      // TEXTURE and BUFFER location url doesn't need type resolving, REGULAR_IMAGE is fine
+      // TEXTURE location url doesn't need type resolving, REGULAR_IMAGE is fine
       mType = ResolveType(url);
     }
   }
@@ -328,14 +328,19 @@ std::string VisualUrl::GetLocation() const
   return GetLocation(mUrl);
 }
 
+std::string VisualUrl::GetLocationWithoutExtension() const
+{
+  return GetLocationWithoutExtension(mUrl);
+}
+
 std::string VisualUrl::CreateTextureUrl(const std::string& location)
 {
   return "dali://" + location;
 }
 
-std::string VisualUrl::CreateBufferUrl(const std::string& location)
+std::string VisualUrl::CreateBufferUrl(const std::string& location, const std::string_view& extension)
 {
-  return "enbuf://" + location;
+  return "enbuf://" + location + std::string(extension);
 }
 
 VisualUrl::ProtocolType VisualUrl::GetProtocolType(const std::string& url)
@@ -353,6 +358,18 @@ std::string VisualUrl::GetLocation(const std::string& url)
   return url;
 }
 
+std::string VisualUrl::GetLocationWithoutExtension(const std::string& url)
+{
+  const auto location = url.find("://");
+  if(std::string::npos != location)
+  {
+    const auto extension = url.find_last_of("."); // Find last position of '.' keyword.
+    const auto locationLength = extension != std::string::npos ? extension - (location + 3u) : std::string::npos;
+    return url.substr(location + 3u, locationLength); // 3 characters forwards from the start of ://, and end of last '.' keyword.
+  }
+  return url;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 9a85ee3..246e4cf 100644 (file)
@@ -20,6 +20,7 @@
 // EXTERNAL INCLUDES
 #include <cstdint>
 #include <string>
+#include <string_view>
 
 namespace Dali
 {
@@ -143,6 +144,11 @@ public:
   std::string GetLocation() const;
 
   /**
+   * @return the location part of the url without extension
+   */
+  std::string GetLocationWithoutExtension() const;
+
+  /**
    * Helper to create a URL of type TEXTURE
    * @param location the location of the texture
    * @return the Url
@@ -151,10 +157,11 @@ public:
 
   /**
    * Helper to create a URL of type BUFFER
-   * @param location the location of the texture
+   * @param[in] location the location of the texture
+   * @param[in] extension the extension of url
    * @return the Url
    */
-  static std::string CreateBufferUrl(const std::string& location);
+  static std::string CreateBufferUrl(const std::string& location, const std::string_view& extension);
 
   /**
    * Helper to get a ProtocolType from url
@@ -170,6 +177,13 @@ public:
    */
   static std::string GetLocation(const std::string& url);
 
+  /**
+   * Helper to get a location from url without extension
+   * @param[in] url the location of the texture
+   * @return the location without extension
+   */
+  static std::string GetLocationWithoutExtension(const std::string& url);
+
 private:
   std::string  mUrl;
   Type         mType;