Add synchronous loading of svg-visual 55/224355/17
authorhuiyu.eun <huiyu.eun@samsung.com>
Mon, 10 Feb 2020 05:20:49 +0000 (14:20 +0900)
committerhuiyu.eun <huiyu.eun@samsung.com>
Wed, 19 Feb 2020 04:46:46 +0000 (13:46 +0900)
Change-Id: I56f3c25bcef325fa9299526b783072fef06aaed2
Signed-off-by: huiyu.eun <huiyu.eun@samsung.com>
automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/image/image-visual.h
dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp
dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/visual-base-impl.cpp
dali-toolkit/internal/visuals/visual-base-impl.h

index a59b0ff..4e72473 100644 (file)
@@ -2432,6 +2432,122 @@ int UtcDaliImageViewLoadRemoteSVG(void)
   END_TEST;
 }
 
   END_TEST;
 }
 
+int UtcDaliImageViewSyncSVGLoading(void)
+{
+  ToolkitTestApplication application;
+
+  tet_infoline("ImageView Testing SVG image sync loading");
+
+  // Sync loading, automatic atlasing for small size image
+  {
+    TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+    callStack.Reset();
+    callStack.Enable(true);
+
+    ImageView imageView = ImageView::New( );
+
+    // Sync loading is used
+    Property::Map syncLoadingMap;
+    syncLoadingMap.Insert( Toolkit::Visual::Property::TYPE,  Toolkit::Visual::IMAGE );
+    syncLoadingMap.Insert( Toolkit::ImageVisual::Property::URL,  TEST_RESOURCE_DIR "/svg1.svg"  );
+    syncLoadingMap.Insert( Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING,  true);
+    imageView.SetProperty( ImageView::Property::IMAGE, syncLoadingMap );
+
+    Stage::GetCurrent().Add( imageView );
+    DALI_TEST_CHECK( imageView );
+
+    application.SendNotification();
+    application.Render(16);
+    Vector3 naturalSize = imageView.GetNaturalSize();
+
+    DALI_TEST_EQUALS( naturalSize.width, 100.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( naturalSize.height, 100.0f, TEST_LOCATION );
+
+  }
+  END_TEST;
+}
+
+int UtcDaliImageViewAsyncSVGLoading(void)
+{
+  ToolkitTestApplication application;
+
+  tet_infoline("ImageView Testing SVG image async loading");
+
+  // Sync loading, automatic atlasing for small size image
+  {
+    TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+    callStack.Reset();
+    callStack.Enable(true);
+
+    ImageView imageView = ImageView::New( );
+
+    // Sync loading is used
+    Property::Map syncLoadingMap;
+    syncLoadingMap.Insert( Toolkit::Visual::Property::TYPE,  Toolkit::Visual::IMAGE );
+    syncLoadingMap.Insert( Toolkit::ImageVisual::Property::URL,  TEST_RESOURCE_DIR "/svg1.svg"  );
+    syncLoadingMap.Insert( Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING,  false);
+    imageView.SetProperty( ImageView::Property::IMAGE, syncLoadingMap );
+
+    Stage::GetCurrent().Add( imageView );
+    DALI_TEST_CHECK( imageView );
+
+    application.SendNotification();
+    application.Render(16);
+    Vector3 naturalSize = imageView.GetNaturalSize();
+
+    DALI_TEST_EQUALS( naturalSize.width, 100.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( naturalSize.height, 100.0f, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliImageViewSVGLoadingSyncSetInvalidValue(void)
+{
+  ToolkitTestApplication application;
+
+  tet_infoline("ImageView Testing SVG image async loading");
+
+  // Sync loading, automatic atlasing for small size image
+  {
+    TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+    callStack.Reset();
+    callStack.Enable(true);
+
+    ImageView imageView = ImageView::New( );
+
+    // Sync loading is used
+    Property::Map syncLoadingMap;
+    syncLoadingMap.Insert( Toolkit::Visual::Property::TYPE,  Toolkit::Visual::IMAGE );
+    syncLoadingMap.Insert( Toolkit::ImageVisual::Property::URL,  TEST_RESOURCE_DIR "/svg1.svg"  );
+
+    // Check to set invalid value
+    // The SYNCHRONOUS_LOADING property must be set to the bool value.
+    // Check if error log is outputted when setting other value like string.
+    // Even if the wrong value is set, the image will be shown normally, and the synchronous value should be the default value(false).
+    syncLoadingMap.Insert( Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, std::to_string(5) );
+    imageView.SetProperty( ImageView::Property::IMAGE, syncLoadingMap );
+
+    Stage::GetCurrent().Add( imageView );
+    DALI_TEST_CHECK( imageView );
+
+    application.SendNotification();
+    application.Render(16);
+    Vector3 naturalSize = imageView.GetNaturalSize();
+    DALI_TEST_EQUALS( naturalSize.width, 100.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( naturalSize.height, 100.0f, TEST_LOCATION );
+
+    Property::Value value = imageView.GetProperty( ImageView::Property::IMAGE );
+    Property::Map* map = value.GetMap();
+    DALI_TEST_CHECK( map );
+
+    Property::Value* sync = map->Find( Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING );
+    DALI_TEST_CHECK( sync );
+    DALI_TEST_EQUALS( false, sync->Get< bool >(), TEST_LOCATION );
+
+  }
+  END_TEST;
+}
+
 int UtcDaliImageViewSvgLoadingFailure(void)
 {
   ToolkitTestApplication application;
 int UtcDaliImageViewSvgLoadingFailure(void)
 {
   ToolkitTestApplication application;
index 59b68fd..5142a50 100644 (file)
@@ -663,11 +663,6 @@ void ImageVisual::CreateNativeImageRenderer( NativeImage& nativeImage )
   mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
 }
 
   mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
 }
 
-bool ImageVisual::IsSynchronousResourceLoading() const
-{
-  return mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
-}
-
 void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection,
                                TextureManager::ReloadPolicy forceReload )
 {
 void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection,
                                TextureManager::ReloadPolicy forceReload )
 {
@@ -688,7 +683,7 @@ void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& t
     : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
 
   textures = textureManager.LoadTexture( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode,
     : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
 
   textures = textureManager.LoadTexture( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode,
-                                         mMaskingData, IsSynchronousResourceLoading(), mTextureId,
+                                         mMaskingData, IsSynchronousLoadingRequired(), mTextureId,
                                          atlasRect, mAtlasRectSize, atlasing, mLoading, mWrapModeU,
                                          mWrapModeV, textureObserver, atlasUploadObserver, atlasManager,
                                          mOrientationCorrection, forceReload, preMultiplyOnLoad);
                                          atlasRect, mAtlasRectSize, atlasing, mLoading, mWrapModeU,
                                          mWrapModeV, textureObserver, atlasUploadObserver, atlasManager,
                                          mOrientationCorrection, forceReload, preMultiplyOnLoad);
@@ -829,7 +824,7 @@ void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const
   map.Clear();
   map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE );
 
   map.Clear();
   map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE );
 
-  bool sync = IsSynchronousResourceLoading();
+  bool sync = IsSynchronousLoadingRequired();
   map.Insert( SYNCHRONOUS_LOADING, sync );
   if( mImageUrl.IsValid() )
   {
   map.Insert( SYNCHRONOUS_LOADING, sync );
   if( mImageUrl.IsValid() )
   {
index ea46680..23dee63 100644 (file)
@@ -331,12 +331,6 @@ private:
   void CreateNativeImageRenderer( NativeImage& nativeImage );
 
   /**
   void CreateNativeImageRenderer( NativeImage& nativeImage );
 
   /**
-   * @brief Query whether resources requires to be loaded synchronously.
-   * @return Returns true if synchronous resource loading is required, false otherwise.
-   */
-  bool IsSynchronousResourceLoading() const;
-
-  /**
    * Creates the texture set and adds the texture to it
    * @param[out] textureRect The texture area of the texture in the atlas.
    * @param[in] url The URL of the image resource to use.
    * Creates the texture set and adds the texture to it
    * @param[out] textureRect The texture area of the texture in the atlas.
    * @param[in] url The URL of the image resource to use.
index 174183e..f0dc4a4 100644 (file)
@@ -49,6 +49,12 @@ RasterizingTask::RasterizingTask( SvgVisual* svgRenderer, NSVGimage* parsedSvg,
   mWidth( width ),
   mHeight( height )
 {
   mWidth( width ),
   mHeight( height )
 {
+  mRasterizer = nsvgCreateRasterizer();
+}
+
+RasterizingTask::~RasterizingTask()
+{
+  nsvgDeleteRasterizer( mRasterizer );
 }
 
 void RasterizingTask::Load()
 }
 
 void RasterizingTask::Load()
@@ -73,7 +79,7 @@ void RasterizingTask::Load()
   }
 }
 
   }
 }
 
-void RasterizingTask::Rasterize( NSVGrasterizer* rasterizer )
+void RasterizingTask::Rasterize( )
 {
   if( mParsedSvg != NULL && mWidth > 0u && mHeight > 0u )
   {
 {
   if( mParsedSvg != NULL && mWidth > 0u && mHeight > 0u )
   {
@@ -84,7 +90,7 @@ void RasterizingTask::Rasterize( NSVGrasterizer* rasterizer )
     unsigned int bufferSize = bufferStride * mHeight;
 
     unsigned char* buffer = new unsigned char [bufferSize];
     unsigned int bufferSize = bufferStride * mHeight;
 
     unsigned char* buffer = new unsigned char [bufferSize];
-    nsvgRasterize(rasterizer, mParsedSvg, 0.f,0.f,scale,
+    nsvgRasterize(mRasterizer, mParsedSvg, 0.f,0.f,scale,
         buffer, mWidth, mHeight,
         bufferStride );
 
         buffer, mWidth, mHeight,
         bufferStride );
 
@@ -111,13 +117,10 @@ SvgRasterizeThread::SvgRasterizeThread( EventThreadCallback* trigger )
 : mTrigger( trigger ),
   mIsThreadWaiting( false )
 {
 : mTrigger( trigger ),
   mIsThreadWaiting( false )
 {
-  mRasterizer = nsvgCreateRasterizer();
 }
 
 SvgRasterizeThread::~SvgRasterizeThread()
 {
 }
 
 SvgRasterizeThread::~SvgRasterizeThread()
 {
-
-  nsvgDeleteRasterizer( mRasterizer );
   delete mTrigger;
 }
 
   delete mTrigger;
 }
 
@@ -264,7 +267,7 @@ void SvgRasterizeThread::Run()
   while( RasterizingTaskPtr task = NextTaskToProcess() )
   {
     task->Load( );
   while( RasterizingTaskPtr task = NextTaskToProcess() )
   {
     task->Load( );
-    task->Rasterize( mRasterizer );
+    task->Rasterize( );
     AddCompletedTask( task );
   }
 }
     AddCompletedTask( task );
   }
 }
index 1c94ca9..b7bdbfd 100644 (file)
@@ -73,10 +73,14 @@ public:
   RasterizingTask( SvgVisual* svgRenderer, NSVGimage* parsedSvg, const VisualUrl& url, float dpi, unsigned int width, unsigned int height );
 
   /**
   RasterizingTask( SvgVisual* svgRenderer, NSVGimage* parsedSvg, const VisualUrl& url, float dpi, unsigned int width, unsigned int height );
 
   /**
-   * Do the rasterization with the given rasterizer.
-   *@param[in] rasterizer The rasterizer that rasterize the SVG to a buffer image
+   * Destructor.
+   */
+  ~RasterizingTask();
+
+  /**
+   * Do the rasterization with the mRasterizer.
    */
    */
-  void Rasterize( NSVGrasterizer* rasterizer );
+  void Rasterize( );
 
   /**
    * Get the svg visual
 
   /**
    * Get the svg visual
@@ -115,6 +119,7 @@ private:
   float           mDpi;
   unsigned int    mWidth;
   unsigned int    mHeight;
   float           mDpi;
   unsigned int    mWidth;
   unsigned int    mHeight;
+  NSVGrasterizer* mRasterizer;
 };
 
 /**
 };
 
 /**
@@ -216,7 +221,6 @@ private:
   Dali::Mutex                mMutex;
   EventThreadCallback*       mTrigger;
 
   Dali::Mutex                mMutex;
   EventThreadCallback*       mTrigger;
 
-  NSVGrasterizer*            mRasterizer;
   bool                       mIsThreadWaiting;
 };
 
   bool                       mIsThreadWaiting;
 };
 
index e4275cd..cc61c12 100644 (file)
@@ -20,6 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/third-party/nanosvg/nanosvg.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/third-party/nanosvg/nanosvg.h>
+#include <dali-toolkit/third-party/nanosvg/nanosvgrast.h>
 #include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
 #include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
@@ -29,6 +30,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/common/stage.h>
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/common/stage.h>
+#include <dali/integration-api/debug.h>
 
 namespace Dali
 {
 
 namespace Dali
 {
@@ -46,7 +48,10 @@ const char * const UNITS("px");
 
 const char * const IMAGE_ATLASING( "atlasing" );
 
 
 const char * const IMAGE_ATLASING( "atlasing" );
 
+const char * const SYNCHRONOUS_LOADING( "synchronousLoading" );
+
 const Dali::Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
 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( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties )
@@ -102,6 +107,10 @@ void SvgVisual::DoSetProperties( const Property::Map& propertyMap )
     {
       DoSetProperty( Toolkit::ImageVisual::Property::ATLASING, keyValue.second );
     }
     {
       DoSetProperty( Toolkit::ImageVisual::Property::ATLASING, keyValue.second );
     }
+    else if( keyValue.first == SYNCHRONOUS_LOADING )
+    {
+      DoSetProperty( Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, keyValue.second );
+    }
   }
 }
 
   }
 }
 
@@ -114,6 +123,26 @@ void SvgVisual::DoSetProperty( Property::Index index, const Property::Value& val
       value.Get( mAttemptAtlasing );
       break;
     }
       value.Get( mAttemptAtlasing );
       break;
     }
+    case Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING:
+    {
+      bool sync = false;
+      if( value.Get( sync ) )
+      {
+        if( sync )
+        {
+          mImpl->mFlags |= Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
+        }
+        else
+        {
+          mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
+        }
+      }
+      else
+      {
+        DALI_LOG_ERROR("ImageVisual: synchronousLoading property has incorrect type\n");
+      }
+      break;
+    }
   }
 }
 
   }
 }
 
@@ -218,7 +247,15 @@ void SvgVisual::AddRasterizationTask( const Vector2& size )
     float meanDpi = ( dpi.height + dpi.width ) * 0.5f;
 
     RasterizingTaskPtr newTask = new RasterizingTask( this, mParsedImage, mImageUrl, meanDpi, width, height );
     float meanDpi = ( dpi.height + dpi.width ) * 0.5f;
 
     RasterizingTaskPtr newTask = new RasterizingTask( this, mParsedImage, mImageUrl, meanDpi, width, height );
-    mFactoryCache.GetSVGRasterizationThread()->AddTask( newTask );
+    if ( IsSynchronousLoadingRequired() )
+    {
+      newTask->Rasterize();
+      ApplyRasterizedImage( newTask->GetParsedImage(), newTask->GetPixelData() );
+    }
+    else
+    {
+      mFactoryCache.GetSVGRasterizationThread()->AddTask( newTask );
+    }
   }
 }
 
   }
 }
 
index 3abe018..b03a5ef 100755 (executable)
@@ -337,6 +337,7 @@ void Visual::Base::CreatePropertyMap( Property::Map& map ) const
   // which is ok, because they have a different key value range.
   map.Insert( Toolkit::Visual::Property::MIX_COLOR, mImpl->mMixColor ); // vec4
   map.Insert( Toolkit::Visual::Property::OPACITY, mImpl->mMixColor.a );
   // which is ok, because they have a different key value range.
   map.Insert( Toolkit::Visual::Property::MIX_COLOR, mImpl->mMixColor ); // vec4
   map.Insert( Toolkit::Visual::Property::OPACITY, mImpl->mMixColor.a );
+  map.Insert( Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, IsSynchronousLoadingRequired() );
 
   auto fittingModeString = Scripting::GetLinearEnumerationName< FittingMode >(
     mImpl->mFittingMode, VISUAL_FITTING_MODE_TABLE, VISUAL_FITTING_MODE_TABLE_COUNT );
 
   auto fittingModeString = Scripting::GetLinearEnumerationName< FittingMode >(
     mImpl->mFittingMode, VISUAL_FITTING_MODE_TABLE, VISUAL_FITTING_MODE_TABLE_COUNT );
@@ -492,6 +493,11 @@ bool Visual::Base::IsResourceReady() const
   return ( mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::READY );
 }
 
   return ( mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::READY );
 }
 
+bool Visual::Base::IsSynchronousLoadingRequired() const
+{
+  return ( mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING );
+}
+
 Toolkit::Visual::ResourceStatus Visual::Base::GetResourceStatus() const
 {
   return mImpl->mResourceStatus;
 Toolkit::Visual::ResourceStatus Visual::Base::GetResourceStatus() const
 {
   return mImpl->mResourceStatus;
index ecf832c..a04fa1f 100644 (file)
@@ -266,6 +266,12 @@ public:
    */
   virtual Base& GetVisualObject();
 
    */
   virtual Base& GetVisualObject();
 
+  /**
+   * @brief Query whether resources requires to be loaded synchronously.
+   * @return Returns true if synchronous resource loading is required, false otherwise.
+   */
+  bool IsSynchronousLoadingRequired() const;
+
  protected:
 
   /**
  protected:
 
   /**