[dali_2.3.22] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / svg / svg-visual.cpp
index a0ced87..49d62ab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
  */
 
 // 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>
 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
-#include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
+#include <dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h>
+#include <dali-toolkit/internal/visuals/svg/svg-task.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
@@ -48,20 +49,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));
+  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));
+  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),
@@ -70,7 +71,8 @@ SvgVisual::SvgVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory&
   mDefaultWidth(0),
   mDefaultHeight(0),
   mPlacementActor(),
-  mRasterizedSize(Vector2::ZERO),
+  mRasterizedSize(-Vector2::ONE), ///< Let we don't use zero since visual size could be zero after trasnform
+  mDesiredSize(size),
   mLoadFailed(false),
   mAttemptAtlasing(false)
 {
@@ -80,6 +82,23 @@ SvgVisual::SvgVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory&
 
 SvgVisual::~SvgVisual()
 {
+  if(Stage::IsInstalled())
+  {
+    if(mLoadingTask)
+    {
+      Dali::AsyncTaskManager::Get().RemoveTask(mLoadingTask);
+    }
+    if(mRasterizingTask)
+    {
+      Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
+    }
+
+    if(mImageUrl.IsBufferResource())
+    {
+      TextureManager& textureManager = mFactoryCache.GetTextureManager();
+      textureManager.RemoveEncodedImageBuffer(mImageUrl.GetUrl());
+    }
+  }
 }
 
 void SvgVisual::OnInitialize()
@@ -92,15 +111,33 @@ void SvgVisual::OnInitialize()
   Vector2 dpi     = Stage::GetCurrent().GetDpi();
   float   meanDpi = (dpi.height + dpi.width) * 0.5f;
 
-  SvgTaskPtr newTask = new SvgLoadingTask(this, mVectorRenderer, mImageUrl, meanDpi);
+  EncodedImageBuffer encodedImageBuffer;
 
-  if(IsSynchronousLoadingRequired() && mImageUrl.IsLocalResource())
+  if(mImageUrl.IsBufferResource())
   {
-    newTask->Process();
+    // 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() || mImageUrl.IsBufferResource()))
+  {
+    mLoadingTask->Process();
+    if(!mLoadingTask->HasSucceeded())
+    {
+      mLoadFailed = true;
+    }
+    mLoadingTask.Reset(); // We don't need it anymore.
   }
   else
   {
-    mFactoryCache.GetSVGRasterizationManager()->AddTask(newTask);
+    Dali::AsyncTaskManager::Get().AddTask(mLoadingTask);
   }
 }
 
@@ -122,6 +159,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);
+    }
   }
 }
 
@@ -154,6 +199,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;
+    }
   }
 }
 
@@ -191,7 +254,12 @@ void SvgVisual::DoSetOnScene(Actor& actor)
 
 void SvgVisual::DoSetOffScene(Actor& actor)
 {
-  mFactoryCache.GetSVGRasterizationManager()->RemoveTask(this);
+  // Remove rasterizing task
+  if(mRasterizingTask)
+  {
+    Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
+    mRasterizingTask.Reset();
+  }
 
   actor.RemoveRenderer(mImpl->mRenderer);
   mPlacementActor.Reset();
@@ -202,7 +270,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();
@@ -234,6 +307,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
@@ -254,30 +329,55 @@ void SvgVisual::AddRasterizationTask(const Vector2& size)
 {
   if(mImpl->mRenderer)
   {
+    // Remove previous task
+    if(mRasterizingTask)
+    {
+      Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
+      mRasterizingTask.Reset();
+    }
+
     unsigned int width  = static_cast<unsigned int>(size.width);
     unsigned int height = static_cast<unsigned int>(size.height);
 
-    SvgTaskPtr newTask = new SvgRasterizingTask(this, mVectorRenderer, width, height);
+    mRasterizingTask = new SvgRasterizingTask(mVectorRenderer, width, height, MakeCallback(this, &SvgVisual::ApplyRasterizedImage));
+
+#ifdef TRACE_ENABLED
+    reinterpret_cast<SvgRasterizingTask*>(mRasterizingTask.Get())->SetUrl(mImageUrl);
+#endif
 
     if(IsSynchronousLoadingRequired() && mImageUrl.IsLocalResource())
     {
-      newTask->Process();
-      ApplyRasterizedImage(newTask->GetPixelData(), newTask->HasSucceeded());
+      mRasterizingTask->Process();
+      ApplyRasterizedImage(mRasterizingTask);
+      mRasterizingTask.Reset(); // We don't need it anymore.
     }
     else
     {
-      mFactoryCache.GetSVGRasterizationManager()->AddTask(newTask);
+      Dali::AsyncTaskManager::Get().AddTask(mRasterizingTask);
     }
   }
 }
 
-void SvgVisual::ApplyRasterizedImage(PixelData rasterizedPixelData, bool success)
+void SvgVisual::ApplyRasterizedImage(SvgTaskPtr task)
 {
-  if(success)
+  SvgVisualPtr self = this; // Keep reference until this API finished
+
+  if(task->HasSucceeded())
   {
+    PixelData rasterizedPixelData = task->GetPixelData();
     if(mDefaultWidth == 0 || mDefaultHeight == 0)
     {
-      mVectorRenderer.GetDefaultSize(mDefaultWidth, mDefaultHeight);
+      task->GetRenderer().GetDefaultSize(mDefaultWidth, mDefaultHeight);
+    }
+
+    // We don't need to keep tasks anymore. reset now.
+    if(task == mLoadingTask)
+    {
+      mLoadingTask.Reset();
+    }
+    if(task == mRasterizingTask)
+    {
+      mRasterizingTask.Reset();
     }
 
     // Rasterization success
@@ -348,10 +448,23 @@ void SvgVisual::ApplyRasterizedImage(PixelData rasterizedPixelData, bool success
       ResourceReady(Toolkit::Visual::ResourceStatus::READY);
     }
   }
-  else if(!success && !mLoadFailed)
+  else if(!mLoadFailed)
   {
     mLoadFailed = true;
 
+    // Remove rasterizing task if we requested before.
+    if(mRasterizingTask)
+    {
+      Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
+      mRasterizingTask.Reset();
+    }
+
+    // We don't need to keep tasks anymore. reset now.
+    if(task == mLoadingTask)
+    {
+      mLoadingTask.Reset();
+    }
+
     Actor actor = mPlacementActor.GetHandle();
     if(actor)
     {
@@ -367,14 +480,24 @@ void SvgVisual::ApplyRasterizedImage(PixelData rasterizedPixelData, bool success
 
 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)
     {
-      mRasterizedSize = visualSize;
-      AddRasterizationTask(visualSize);
+      mRasterizedSize = size;
+      AddRasterizationTask(size);
     }
   }
 
@@ -400,7 +523,7 @@ Shader SvgVisual::GenerateShader() const
   {
     shader = mImageVisualShaderFactory.GetShader(
       mFactoryCache,
-      ImageVisualShaderFeature::FeatureBuilder()
+      ImageVisualShaderFeatureBuilder()
         .EnableTextureAtlas(mAttemptAtlasing)
         .EnableRoundedCorner(IsRoundedCornerRequired())
         .EnableBorderline(IsBorderlineRequired()));