Support asynchronous svg loading
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / svg / svg-visual.cpp
index 9a47462..bddb7f0 100644 (file)
@@ -27,7 +27,6 @@
 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
 
 // EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/file-loader.h>
 #include <dali/devel-api/common/stage.h>
 #include <dali/integration-api/debug.h>
 
@@ -49,7 +48,6 @@ 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();
   svgVisual->SetProperties(properties);
   svgVisual->Initialize();
   return svgVisual;
@@ -58,7 +56,6 @@ SvgVisualPtr SvgVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderF
 SvgVisualPtr SvgVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl)
 {
   SvgVisualPtr svgVisual(new SvgVisual(factoryCache, shaderFactory, imageUrl));
-  svgVisual->Load();
   svgVisual->Initialize();
   return svgVisual;
 }
@@ -72,7 +69,7 @@ SvgVisual::SvgVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory&
   mDefaultWidth(0),
   mDefaultHeight(0),
   mPlacementActor(),
-  mVisualSize(Vector2::ZERO),
+  mRasterizedSize(Vector2::ZERO),
   mLoadFailed(false),
   mAttemptAtlasing(false)
 {
@@ -169,8 +166,11 @@ void SvgVisual::DoSetOnScene(Actor& actor)
   }
   else
   {
-    // SVG visual needs it's size set before it can be rasterized hence set ResourceReady once on stage
-    ResourceReady(Toolkit::Visual::ResourceStatus::READY);
+    if(mImpl->mEventObserver)
+    {
+      // SVG visual needs it's size set before it can be rasterized hence request relayout once on stage
+      mImpl->mEventObserver->RelayoutRequest(*this);
+    }
   }
 }
 
@@ -182,13 +182,31 @@ void SvgVisual::DoSetOffScene(Actor& actor)
   mPlacementActor.Reset();
 
   // Reset the visual size to zero so that when adding the actor back to stage the SVG rasterization is forced
-  mVisualSize = Vector2::ZERO;
+  mRasterizedSize = Vector2::ZERO;
 }
 
 void SvgVisual::GetNaturalSize(Vector2& naturalSize)
 {
-  naturalSize.x = mDefaultWidth;
-  naturalSize.y = mDefaultHeight;
+  if(mLoadFailed && mImpl->mRenderer)
+  {
+    // Load failed, use broken image size
+    auto textureSet = mImpl->mRenderer.GetTextures();
+    if(textureSet && textureSet.GetTextureCount())
+    {
+      auto texture = textureSet.GetTexture(0);
+      if(texture)
+      {
+        naturalSize.x = texture.GetWidth();
+        naturalSize.y = texture.GetHeight();
+        return;
+      }
+    }
+  }
+  else
+  {
+    naturalSize.x = mDefaultWidth;
+    naturalSize.y = mDefaultHeight;
+  }
 }
 
 void SvgVisual::DoCreatePropertyMap(Property::Map& map) const
@@ -217,34 +235,6 @@ void SvgVisual::EnablePreMultipliedAlpha(bool preMultiplied)
   }
 }
 
-void SvgVisual::Load()
-{
-  // load remote resource on svg rasterize thread.
-  if(mImageUrl.IsLocalResource())
-  {
-    Dali::Vector<uint8_t> 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)
@@ -256,11 +246,12 @@ void SvgVisual::AddRasterizationTask(const Vector2& size)
     float   meanDpi = (dpi.height + dpi.width) * 0.5f;
 
     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());
+      ApplyRasterizedImage(newTask->GetPixelData(), newTask->IsLoaded());
     }
     else
     {
@@ -269,10 +260,18 @@ void SvgVisual::AddRasterizationTask(const Vector2& size)
   }
 }
 
-void SvgVisual::ApplyRasterizedImage(VectorImageRenderer vectorRenderer, PixelData rasterizedPixelData, bool isLoaded)
+void SvgVisual::ApplyRasterizedImage(PixelData rasterizedPixelData, bool isLoaded)
 {
   if(isLoaded && rasterizedPixelData && IsOnScene())
   {
+    if(mDefaultWidth == 0 || mDefaultHeight == 0)
+    {
+      mVectorRenderer.GetDefaultSize(mDefaultWidth, mDefaultHeight);
+    }
+
+    mRasterizedSize.x = static_cast<float>(rasterizedPixelData.GetWidth());
+    mRasterizedSize.y = static_cast<float>(rasterizedPixelData.GetHeight());
+
     TextureSet currentTextureSet = mImpl->mRenderer.GetTextures();
     if(mImpl->mFlags & Impl::IS_ATLASING_APPLIED)
     {
@@ -336,6 +335,8 @@ void SvgVisual::ApplyRasterizedImage(VectorImageRenderer vectorRenderer, PixelDa
   }
   else if(!isLoaded || !rasterizedPixelData)
   {
+    mLoadFailed = true;
+
     Actor actor = mPlacementActor.GetHandle();
     if(actor)
     {
@@ -355,10 +356,10 @@ void SvgVisual::OnSetTransform()
 
   if(IsOnScene() && !mLoadFailed)
   {
-    if(visualSize != mVisualSize)
+    if(visualSize != mRasterizedSize || mDefaultWidth == 0 || mDefaultHeight == 0)
     {
+      mRasterizedSize = visualSize;
       AddRasterizationTask(visualSize);
-      mVisualSize = visualSize;
     }
   }