From: Eunki Hong Date: Sat, 28 Oct 2023 16:17:50 +0000 (+0900) Subject: (Vector) Support EncodedImageBuffer can use for vector image X-Git-Tag: dali_2.2.52~2^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=47beafb2e5b7a6a46b6cb2875ce16dc19e05902d (Vector) Support EncodedImageBuffer can use for vector image 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 --- diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp index 3e9a117..f9df7d8 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp @@ -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; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualUrl.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualUrl.cpp index 3003ae4..3e5e8eb 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualUrl.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualUrl.cpp @@ -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; } diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.cpp index ef389ed..600a866 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.cpp @@ -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. @@ -21,22 +21,22 @@ 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 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; } diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.h index 96fbe46..3b6e28b 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-encoded-image-buffer.h @@ -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 diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp index 2f2901f..0a82fb4 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp @@ -879,6 +879,86 @@ int UtcDaliImageViewSyncLoadingEncodedBuffer(void) END_TEST; } +int UtcDaliImageViewEncodedBufferWithSvg(void) +{ + ToolkitTestApplication application; + TestGlAbstraction& gl = application.GetGlAbstraction(); + const std::vector& 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& 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& 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& 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; diff --git a/dali-toolkit/internal/image-loader/loading-task.cpp b/dali-toolkit/internal/image-loader/loading-task.cpp index 74788cb..2c08799 100644 --- a/dali-toolkit/internal/image-loader/loading-task.cpp +++ b/dali-toolkit/internal/image-loader/loading-task.cpp @@ -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()) { diff --git a/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp b/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp index fc77c6f..4343a84 100644 --- a/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp +++ b/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp @@ -21,6 +21,8 @@ // EXTERNAL HEADERS #include #include +#include +#include // 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 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); diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp index 982d6dd..09c4418 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp @@ -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); diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp index d7f14ba..c1e9d56 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp @@ -19,6 +19,7 @@ #include // EXTERNAL INCLUDES +#include #include #include #include @@ -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 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) { diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h index c3ac749..123d685 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -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 mAnimationData[2]; VectorAnimationThread& mVectorAnimationThread; diff --git a/dali-toolkit/internal/visuals/svg/svg-task.cpp b/dali-toolkit/internal/visuals/svg/svg-task.cpp index de551d6..5f8ed8c 100644 --- a/dali-toolkit/internal/visuals/svg/svg-task.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-task.cpp @@ -16,7 +16,7 @@ */ // CLASS HEADER -#include "svg-task.h" +#include // EXTERNAL INCLUDES #include @@ -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 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)) diff --git a/dali-toolkit/internal/visuals/svg/svg-task.h b/dali-toolkit/internal/visuals/svg/svg-task.h index beeaee4..8b421d4 100644 --- a/dali-toolkit/internal/visuals/svg/svg-task.h +++ b/dali-toolkit/internal/visuals/svg/svg-task.h @@ -22,6 +22,7 @@ #include #include #include +#include #include // 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 diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.cpp b/dali-toolkit/internal/visuals/svg/svg-visual.cpp index 33b7781..8d64c8f 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-visual.cpp @@ -16,7 +16,7 @@ */ // CLASS HEADER -#include "svg-visual.h" +#include // INTERNAL INCLUDES #include @@ -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()) diff --git a/dali-toolkit/internal/visuals/visual-url.cpp b/dali-toolkit/internal/visuals/visual-url.cpp index fc19714..93c1e78 100644 --- a/dali-toolkit/internal/visuals/visual-url.cpp +++ b/dali-toolkit/internal/visuals/visual-url.cpp @@ -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 diff --git a/dali-toolkit/internal/visuals/visual-url.h b/dali-toolkit/internal/visuals/visual-url.h index 9a85ee3..246e4cf 100644 --- a/dali-toolkit/internal/visuals/visual-url.h +++ b/dali-toolkit/internal/visuals/visual-url.h @@ -20,6 +20,7 @@ // EXTERNAL INCLUDES #include #include +#include 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;