From 7f8001319223b3168789bb5f35c5a96868b97d13 Mon Sep 17 00:00:00 2001 From: "huiyu.eun" Date: Mon, 10 Feb 2020 14:20:49 +0900 Subject: [PATCH] Add synchronous loading of svg-visual Change-Id: I56f3c25bcef325fa9299526b783072fef06aaed2 Signed-off-by: huiyu.eun --- .../src/dali-toolkit/utc-Dali-ImageView.cpp | 116 +++++++++++++++++++++ .../internal/visuals/image/image-visual.cpp | 9 +- dali-toolkit/internal/visuals/image/image-visual.h | 6 -- .../internal/visuals/svg/svg-rasterize-thread.cpp | 15 +-- .../internal/visuals/svg/svg-rasterize-thread.h | 12 ++- dali-toolkit/internal/visuals/svg/svg-visual.cpp | 39 ++++++- dali-toolkit/internal/visuals/visual-base-impl.cpp | 6 ++ dali-toolkit/internal/visuals/visual-base-impl.h | 6 ++ 8 files changed, 185 insertions(+), 24 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp index a59b0ff..4e72473 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp @@ -2432,6 +2432,122 @@ int UtcDaliImageViewLoadRemoteSVG(void) 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; diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index 59b68fd..5142a50 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -663,11 +663,6 @@ void ImageVisual::CreateNativeImageRenderer( NativeImage& nativeImage ) 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 ) { @@ -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, - mMaskingData, IsSynchronousResourceLoading(), mTextureId, + mMaskingData, IsSynchronousLoadingRequired(), mTextureId, 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 ); - bool sync = IsSynchronousResourceLoading(); + bool sync = IsSynchronousLoadingRequired(); map.Insert( SYNCHRONOUS_LOADING, sync ); if( mImageUrl.IsValid() ) { diff --git a/dali-toolkit/internal/visuals/image/image-visual.h b/dali-toolkit/internal/visuals/image/image-visual.h index ea46680..23dee63 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.h +++ b/dali-toolkit/internal/visuals/image/image-visual.h @@ -331,12 +331,6 @@ private: 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. diff --git a/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp b/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp index 174183e..f0dc4a4 100644 --- a/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp @@ -49,6 +49,12 @@ RasterizingTask::RasterizingTask( SvgVisual* svgRenderer, NSVGimage* parsedSvg, mWidth( width ), mHeight( height ) { + mRasterizer = nsvgCreateRasterizer(); +} + +RasterizingTask::~RasterizingTask() +{ + nsvgDeleteRasterizer( mRasterizer ); } 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 ) { @@ -84,7 +90,7 @@ void RasterizingTask::Rasterize( NSVGrasterizer* rasterizer ) 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 ); @@ -111,13 +117,10 @@ SvgRasterizeThread::SvgRasterizeThread( EventThreadCallback* trigger ) : mTrigger( trigger ), mIsThreadWaiting( false ) { - mRasterizer = nsvgCreateRasterizer(); } SvgRasterizeThread::~SvgRasterizeThread() { - - nsvgDeleteRasterizer( mRasterizer ); delete mTrigger; } @@ -264,7 +267,7 @@ void SvgRasterizeThread::Run() while( RasterizingTaskPtr task = NextTaskToProcess() ) { task->Load( ); - task->Rasterize( mRasterizer ); + task->Rasterize( ); AddCompletedTask( task ); } } diff --git a/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h b/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h index 1c94ca9..b7bdbfd 100644 --- a/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h +++ b/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h @@ -73,10 +73,14 @@ public: 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 @@ -115,6 +119,7 @@ private: float mDpi; unsigned int mWidth; unsigned int mHeight; + NSVGrasterizer* mRasterizer; }; /** @@ -216,7 +221,6 @@ private: Dali::Mutex mMutex; EventThreadCallback* mTrigger; - NSVGrasterizer* mRasterizer; bool mIsThreadWaiting; }; diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.cpp b/dali-toolkit/internal/visuals/svg/svg-visual.cpp index e4275cd..cc61c12 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-visual.cpp @@ -20,6 +20,7 @@ // INTERNAL INCLUDES #include +#include #include #include #include @@ -29,6 +30,7 @@ // EXTERNAL INCLUDES #include +#include namespace Dali { @@ -46,7 +48,10 @@ const char * const UNITS("px"); 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); + } 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 ); } + 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; } + 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 ); - mFactoryCache.GetSVGRasterizationThread()->AddTask( newTask ); + if ( IsSynchronousLoadingRequired() ) + { + newTask->Rasterize(); + ApplyRasterizedImage( newTask->GetParsedImage(), newTask->GetPixelData() ); + } + else + { + mFactoryCache.GetSVGRasterizationThread()->AddTask( newTask ); + } } } diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index 3abe018..b03a5ef 100755 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -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 ); + map.Insert( Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, IsSynchronousLoadingRequired() ); 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 ); } +bool Visual::Base::IsSynchronousLoadingRequired() const +{ + return ( mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING ); +} + Toolkit::Visual::ResourceStatus Visual::Base::GetResourceStatus() const { return mImpl->mResourceStatus; diff --git a/dali-toolkit/internal/visuals/visual-base-impl.h b/dali-toolkit/internal/visuals/visual-base-impl.h index ecf832c..a04fa1f 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-impl.h @@ -266,6 +266,12 @@ public: */ 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: /** -- 2.7.4