X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fsvg%2Fsvg-visual.cpp;h=8fcbf52f86a95c8f6c57da68f78b702a99091847;hb=d0e761f11ac3a6a65ae7af1d48e559268e5316b3;hp=6851c754b6b9f06a87a399b01cf504f249a594ef;hpb=df0ba815340cb09f10cb3e84358718310ef0bffb;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.cpp b/dali-toolkit/internal/visuals/svg/svg-visual.cpp index 6851c75..8fcbf52 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-visual.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. @@ -21,15 +21,15 @@ // INTERNAL INCLUDES #include #include -#include +#include #include #include #include // EXTERNAL INCLUDES -#include #include #include +#include namespace Dali { @@ -39,7 +39,7 @@ namespace Internal { namespace { -const int CUSTOM_PROPERTY_COUNT(6); // atlas + corner/border +const int CUSTOM_PROPERTY_COUNT(1); // atlas // property name const Dali::Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); @@ -48,22 +48,20 @@ const Dali::Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); SvgVisualPtr SvgVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties) { - SvgVisualPtr svgVisual(new SvgVisual(factoryCache, shaderFactory, imageUrl)); - svgVisual->Load(); + SvgVisualPtr svgVisual(new SvgVisual(factoryCache, shaderFactory, imageUrl, ImageDimensions{})); svgVisual->SetProperties(properties); svgVisual->Initialize(); return svgVisual; } -SvgVisualPtr SvgVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl) +SvgVisualPtr SvgVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, ImageDimensions size) { - SvgVisualPtr svgVisual(new SvgVisual(factoryCache, shaderFactory, imageUrl)); - svgVisual->Load(); + SvgVisualPtr svgVisual(new SvgVisual(factoryCache, shaderFactory, imageUrl, size)); svgVisual->Initialize(); return svgVisual; } -SvgVisual::SvgVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl) +SvgVisual::SvgVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, ImageDimensions size) : Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::SVG), mImageVisualShaderFactory(shaderFactory), mAtlasRect(FULL_TEXTURE_RECT), @@ -73,6 +71,7 @@ SvgVisual::SvgVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& mDefaultHeight(0), mPlacementActor(), mRasterizedSize(Vector2::ZERO), + mDesiredSize(size), mLoadFailed(false), mAttemptAtlasing(false) { @@ -82,14 +81,44 @@ SvgVisual::SvgVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& SvgVisual::~SvgVisual() { + if(Stage::IsInstalled()) + { + if(mLoadingTask) + { + Dali::AsyncTaskManager::Get().RemoveTask(mLoadingTask); + } + if(mRasterizingTask) + { + Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask); + } + } } void SvgVisual::OnInitialize() { Shader shader = GenerateShader(); Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY); - mImpl->mRenderer = VisualRenderer::New(geometry, shader); + mImpl->mRenderer = DecoratedVisualRenderer::New(geometry, shader); mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT); + + Vector2 dpi = Stage::GetCurrent().GetDpi(); + float meanDpi = (dpi.height + dpi.width) * 0.5f; + + mLoadingTask = new SvgLoadingTask(mVectorRenderer, mImageUrl, meanDpi, MakeCallback(this, &SvgVisual::ApplyRasterizedImage)); + + if(IsSynchronousLoadingRequired() && mImageUrl.IsLocalResource()) + { + mLoadingTask->Process(); + if(!mLoadingTask->HasSucceeded()) + { + mLoadFailed = true; + } + mLoadingTask.Reset(); // We don't need it anymore. + } + else + { + Dali::AsyncTaskManager::Get().AddTask(mLoadingTask); + } } void SvgVisual::DoSetProperties(const Property::Map& propertyMap) @@ -110,6 +139,14 @@ void SvgVisual::DoSetProperties(const Property::Map& propertyMap) { DoSetProperty(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, keyValue.second); } + else if(keyValue.first == IMAGE_DESIRED_WIDTH) + { + DoSetProperty(Toolkit::ImageVisual::Property::DESIRED_WIDTH, keyValue.second); + } + else if(keyValue.first == IMAGE_DESIRED_HEIGHT) + { + DoSetProperty(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, keyValue.second); + } } } @@ -142,6 +179,24 @@ void SvgVisual::DoSetProperty(Property::Index index, const Property::Value& valu } break; } + case Toolkit::ImageVisual::Property::DESIRED_WIDTH: + { + int32_t desiredWidth = 0; + if(value.Get(desiredWidth)) + { + mDesiredSize.SetWidth(desiredWidth); + } + break; + } + case Toolkit::ImageVisual::Property::DESIRED_HEIGHT: + { + int32_t desiredHeight = 0; + if(value.Get(desiredHeight)) + { + mDesiredSize.SetHeight(desiredHeight); + } + break; + } } } @@ -179,7 +234,17 @@ void SvgVisual::DoSetOnScene(Actor& actor) void SvgVisual::DoSetOffScene(Actor& actor) { - mFactoryCache.GetSVGRasterizationThread()->RemoveTask(this); + // Remove loading & rasterizing task + if(mLoadingTask) + { + Dali::AsyncTaskManager::Get().RemoveTask(mLoadingTask); + mLoadingTask.Reset(); + } + if(mRasterizingTask) + { + Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask); + mRasterizingTask.Reset(); + } actor.RemoveRenderer(mImpl->mRenderer); mPlacementActor.Reset(); @@ -190,7 +255,12 @@ void SvgVisual::DoSetOffScene(Actor& actor) void SvgVisual::GetNaturalSize(Vector2& naturalSize) { - if(mLoadFailed && mImpl->mRenderer) + if(mDesiredSize.GetWidth() > 0 && mDesiredSize.GetHeight() > 0) + { + naturalSize.x = mDesiredSize.GetWidth(); + naturalSize.y = mDesiredSize.GetHeight(); + } + else if(mLoadFailed && mImpl->mRenderer) { // Load failed, use broken image size auto textureSet = mImpl->mRenderer.GetTextures(); @@ -222,6 +292,8 @@ void SvgVisual::DoCreatePropertyMap(Property::Map& map) const map.Insert(Toolkit::ImageVisual::Property::ATLASING, mAttemptAtlasing); } map.Insert(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, IsSynchronousLoadingRequired()); + map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth()); + map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight()); } void SvgVisual::DoCreateInstancePropertyMap(Property::Map& map) const @@ -238,34 +310,6 @@ void SvgVisual::EnablePreMultipliedAlpha(bool preMultiplied) } } -void SvgVisual::Load() -{ - // load remote resource on svg rasterize thread. - if(mImageUrl.IsLocalResource()) - { - Dali::Vector buffer; - if(Dali::FileLoader::ReadFile(mImageUrl.GetUrl(), buffer)) - { - buffer.PushBack('\0'); - - Vector2 dpi = Stage::GetCurrent().GetDpi(); - float meanDpi = (dpi.height + dpi.width) * 0.5f; - if(!mVectorRenderer.Load(buffer, meanDpi)) - { - mLoadFailed = true; - DALI_LOG_ERROR("SvgVisual::Load: Failed to load file! [%s]\n", mImageUrl.GetUrl().c_str()); - return; - } - mVectorRenderer.GetDefaultSize(mDefaultWidth, mDefaultHeight); - } - else - { - mLoadFailed = true; - DALI_LOG_ERROR("SvgVisual::Load: Failed to read file! [%s]\n", mImageUrl.GetUrl().c_str()); - } - } -} - void SvgVisual::AddRasterizationTask(const Vector2& size) { if(mImpl->mRenderer) @@ -273,97 +317,100 @@ void SvgVisual::AddRasterizationTask(const Vector2& size) unsigned int width = static_cast(size.width); unsigned int height = static_cast(size.height); - Vector2 dpi = Stage::GetCurrent().GetDpi(); - float meanDpi = (dpi.height + dpi.width) * 0.5f; + mRasterizingTask = new SvgRasterizingTask(mVectorRenderer, width, height, MakeCallback(this, &SvgVisual::ApplyRasterizedImage)); - RasterizingTaskPtr newTask = new RasterizingTask(this, mVectorRenderer, mImageUrl, meanDpi, width, height); if(IsSynchronousLoadingRequired() && mImageUrl.IsLocalResource()) { - newTask->Load(); - newTask->Rasterize(); - ApplyRasterizedImage(newTask->GetVectorRenderer(), newTask->GetPixelData(), newTask->IsLoaded()); + mRasterizingTask->Process(); + ApplyRasterizedImage(mRasterizingTask); + mRasterizingTask.Reset(); // We don't need it anymore. } else { - mFactoryCache.GetSVGRasterizationThread()->AddTask(newTask); + Dali::AsyncTaskManager::Get().AddTask(mRasterizingTask); } } } -void SvgVisual::ApplyRasterizedImage(VectorImageRenderer vectorRenderer, PixelData rasterizedPixelData, bool isLoaded) +void SvgVisual::ApplyRasterizedImage(SvgTaskPtr task) { - if(isLoaded && rasterizedPixelData && IsOnScene()) + if(task->HasSucceeded()) { + PixelData rasterizedPixelData = task->GetPixelData(); if(mDefaultWidth == 0 || mDefaultHeight == 0) { - mVectorRenderer.GetDefaultSize(mDefaultWidth, mDefaultHeight); + task->GetRenderer().GetDefaultSize(mDefaultWidth, mDefaultHeight); } - mRasterizedSize.x = static_cast(rasterizedPixelData.GetWidth()); - mRasterizedSize.y = static_cast(rasterizedPixelData.GetHeight()); - - TextureSet currentTextureSet = mImpl->mRenderer.GetTextures(); - if(mImpl->mFlags & Impl::IS_ATLASING_APPLIED) + // Rasterization success + if(rasterizedPixelData && IsOnScene()) { - mFactoryCache.GetAtlasManager()->Remove(currentTextureSet, mAtlasRect); - } - - TextureSet textureSet; + mRasterizedSize.x = static_cast(rasterizedPixelData.GetWidth()); + mRasterizedSize.y = static_cast(rasterizedPixelData.GetHeight()); - if(mAttemptAtlasing && !mImpl->mCustomShader) - { - Vector4 atlasRect; - textureSet = mFactoryCache.GetAtlasManager()->Add(atlasRect, rasterizedPixelData); - if(textureSet) // atlasing + TextureSet currentTextureSet = mImpl->mRenderer.GetTextures(); + if(mImpl->mFlags & Impl::IS_ATLASING_APPLIED) { - if(textureSet != currentTextureSet) - { - mImpl->mRenderer.SetTextures(textureSet); - } - mImpl->mRenderer.RegisterProperty(ATLAS_RECT_UNIFORM_NAME, atlasRect); - mAtlasRect = atlasRect; - mImpl->mFlags |= Impl::IS_ATLASING_APPLIED; + mFactoryCache.GetAtlasManager()->Remove(currentTextureSet, mAtlasRect); } - } - if(!textureSet) // no atlasing - mAttemptAtlasing is false or adding to atlas is failed - { - Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, rasterizedPixelData.GetWidth(), rasterizedPixelData.GetHeight()); - texture.Upload(rasterizedPixelData); - mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; + TextureSet textureSet; - if(mAtlasRect == FULL_TEXTURE_RECT) + if(mAttemptAtlasing && !mImpl->mCustomShader) { - textureSet = currentTextureSet; + Vector4 atlasRect; + textureSet = mFactoryCache.GetAtlasManager()->Add(atlasRect, rasterizedPixelData); + if(textureSet) // atlasing + { + if(textureSet != currentTextureSet) + { + mImpl->mRenderer.SetTextures(textureSet); + } + mImpl->mRenderer.RegisterProperty(ATLAS_RECT_UNIFORM_NAME, atlasRect); + mAtlasRect = atlasRect; + mImpl->mFlags |= Impl::IS_ATLASING_APPLIED; + } } - else + + if(!textureSet) // no atlasing - mAttemptAtlasing is false or adding to atlas is failed { - textureSet = TextureSet::New(); - mImpl->mRenderer.SetTextures(textureSet); + Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, rasterizedPixelData.GetWidth(), rasterizedPixelData.GetHeight()); + texture.Upload(rasterizedPixelData); + mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; + + if(mAtlasRect == FULL_TEXTURE_RECT) + { + textureSet = currentTextureSet; + } + else + { + textureSet = TextureSet::New(); + mImpl->mRenderer.SetTextures(textureSet); + + mImpl->mRenderer.RegisterProperty(ATLAS_RECT_UNIFORM_NAME, FULL_TEXTURE_RECT); + mAtlasRect = FULL_TEXTURE_RECT; + } - mImpl->mRenderer.RegisterProperty(ATLAS_RECT_UNIFORM_NAME, FULL_TEXTURE_RECT); - mAtlasRect = FULL_TEXTURE_RECT; + if(textureSet) + { + textureSet.SetTexture(0, texture); + } } - if(textureSet) + // Rasterized pixels are uploaded to texture. If weak handle is holding a placement actor, it is the time to add the renderer to actor. + Actor actor = mPlacementActor.GetHandle(); + if(actor) { - textureSet.SetTexture(0, texture); + actor.AddRenderer(mImpl->mRenderer); + // reset the weak handle so that the renderer only get added to actor once + mPlacementActor.Reset(); } - } - // Rasterized pixels are uploaded to texture. If weak handle is holding a placement actor, it is the time to add the renderer to actor. - Actor actor = mPlacementActor.GetHandle(); - if(actor) - { - actor.AddRenderer(mImpl->mRenderer); - // reset the weak handle so that the renderer only get added to actor once - mPlacementActor.Reset(); + // Svg loaded and ready to display + ResourceReady(Toolkit::Visual::ResourceStatus::READY); } - - // Svg loaded and ready to display - ResourceReady(Toolkit::Visual::ResourceStatus::READY); } - else if(!isLoaded || !rasterizedPixelData) + else if(!mLoadFailed) { mLoadFailed = true; @@ -378,18 +425,38 @@ void SvgVisual::ApplyRasterizedImage(VectorImageRenderer vectorRenderer, PixelDa ResourceReady(Toolkit::Visual::ResourceStatus::FAILED); } + + // We don't need to keep tasks anymore. reset now. + if(task == mLoadingTask) + { + mLoadingTask.Reset(); + } + if(task == mRasterizingTask) + { + mRasterizingTask.Reset(); + } } void SvgVisual::OnSetTransform() { - Vector2 visualSize = mImpl->mTransform.GetVisualSize(mImpl->mControlSize); - if(IsOnScene() && !mLoadFailed) { - if(visualSize != mRasterizedSize || mDefaultWidth == 0 || mDefaultHeight == 0) + Vector2 size; + if(mDesiredSize.GetWidth() > 0 && mDesiredSize.GetHeight() > 0) + { + // Use desired size + size = Vector2(mDesiredSize.GetWidth(), mDesiredSize.GetHeight()); + } + else + { + // Use visual size + size = mImpl->mTransform.GetVisualSize(mImpl->mControlSize); + } + + if(size != mRasterizedSize || mDefaultWidth == 0 || mDefaultHeight == 0) { - AddRasterizationTask(visualSize); - mRasterizedSize = visualSize; + mRasterizedSize = size; + AddRasterizationTask(size); } }