/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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-rasterize-thread.h"
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/thread-settings.h>
+#include <dali/devel-api/adaptor-framework/file-loader.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
+#include <dali/integration-api/debug.h>
+
// INTERNAL INCLUDES
-#include <dali-toolkit/third-party/nanosvg/nanosvgrast.h>
#include <dali-toolkit/internal/visuals/svg/svg-visual.h>
namespace Dali
namespace Internal
{
-RasterizingTask::RasterizingTask( SvgVisual* svgRenderer, NSVGimage* parsedSvg, unsigned int width, unsigned int height )
+RasterizingTask::RasterizingTask( SvgVisual* svgRenderer, VectorImageRenderer vectorRenderer, const VisualUrl& url, float dpi, unsigned int width, unsigned int height, bool loaded)
: mSvgVisual( svgRenderer ),
- mParsedSvg( parsedSvg ),
+ mVectorRenderer( vectorRenderer ),
+ mUrl( url ),
+ mDpi( dpi ),
mWidth( width ),
- mHeight( height )
+ mHeight( height ),
+ mLoaded( loaded )
+{
+
+}
+
+RasterizingTask::~RasterizingTask()
+{
+}
+
+void RasterizingTask::Load()
{
+ if(!mLoaded && !mUrl.IsLocalResource())
+ {
+ Dali::Vector<uint8_t> remoteBuffer;
+ if(!Dali::FileLoader::DownloadFileSynchronously(mUrl.GetUrl(), remoteBuffer))
+ {
+ DALI_LOG_ERROR("RasterizingTask::Load: Failed to download file! [%s]\n", mUrl.GetUrl().c_str());
+ return;
+ }
+
+ remoteBuffer.PushBack('\0');
+
+ if(!mVectorRenderer.Load(remoteBuffer, mDpi))
+ {
+ DALI_LOG_ERROR("RasterizingTask::Load:Failed to load data! [%s]\n", mUrl.GetUrl().c_str());
+ return;
+ }
+
+ mLoaded = true;
+ }
}
-void RasterizingTask::Rasterize( NSVGrasterizer* rasterizer )
+void RasterizingTask::Rasterize()
{
- if( mWidth > 0u && mHeight > 0u )
+ if(mWidth <= 0u || mHeight <= 0u)
{
- float scaleX = static_cast<float>( mWidth ) / mParsedSvg->width;
- float scaleY = static_cast<float>( mHeight ) / mParsedSvg->height;
- float scale = scaleX < scaleY ? scaleX : scaleY;
- unsigned int bufferStride = mWidth*Pixel::GetBytesPerPixel( Pixel::RGBA8888 );
- unsigned int bufferSize = bufferStride * mHeight;
+ DALI_LOG_ERROR("RasterizingTask::Rasterize: Size is zero!\n");
+ return;
+ }
- unsigned char* buffer = new unsigned char [bufferSize];
- nsvgRasterize(rasterizer, mParsedSvg, 0.f,0.f,scale,
- buffer, mWidth, mHeight,
- bufferStride );
+ Devel::PixelBuffer pixelBuffer = Devel::PixelBuffer::New(mWidth, mHeight, Dali::Pixel::RGBA8888);
- mPixelData = Dali::PixelData::New( buffer, bufferSize, mWidth, mHeight, Pixel::RGBA8888, Dali::PixelData::DELETE_ARRAY );
+ uint32_t defaultWidth, defaultHeight;
+ mVectorRenderer.GetDefaultSize(defaultWidth, defaultHeight);
+
+ float scaleX = static_cast<float>(mWidth) / static_cast<float>(defaultWidth);
+ float scaleY = static_cast<float>(mHeight) / static_cast<float>(defaultHeight);
+ float scale = scaleX < scaleY ? scaleX : scaleY;
+
+ if(!mVectorRenderer.Rasterize(pixelBuffer, scale))
+ {
+ DALI_LOG_ERROR("RasterizingTask::Rasterize: Rasterize is failed! [%s]\n", mUrl.GetUrl().c_str());
+ return;
}
+
+ mPixelData = Devel::PixelBuffer::Convert(pixelBuffer);
+}
+
+VectorImageRenderer RasterizingTask::GetVectorRenderer() const
+{
+ return mVectorRenderer;
+}
+
+bool RasterizingTask::IsLoaded() const
+{
+ return mLoaded;
}
SvgVisual* RasterizingTask::GetSvgVisual() const
return mPixelData;
}
-SvgRasterizeThread::SvgRasterizeThread( EventThreadCallback* trigger )
-: mTrigger( trigger ),
- mIsThreadWaiting( false )
+SvgRasterizeThread::SvgRasterizeThread()
+: mTrigger( new EventThreadCallback( MakeCallback( this, &SvgRasterizeThread::ApplyRasterizedSVGToSampler ) ) ),
+ mLogFactory( Dali::Adaptor::Get().GetLogFactory() ),
+ mIsThreadWaiting( false ),
+ mProcessorRegistered( false )
{
- mRasterizer = nsvgCreateRasterizer();
}
SvgRasterizeThread::~SvgRasterizeThread()
{
-
- nsvgDeleteRasterizer( mRasterizer );
- delete mTrigger;
+ if( mProcessorRegistered )
+ {
+ Adaptor::Get().UnregisterProcessor( *this );
+ }
}
void SvgRasterizeThread::TerminateThread( SvgRasterizeThread*& thread )
}
}
mRasterizeTasks.push_back( task );
+
+ if( !mProcessorRegistered )
+ {
+ Adaptor::Get().RegisterProcessor( *this );
+ mProcessorRegistered = true;
+ }
}
if( wasEmpty)
return nextTask;
}
-void SvgRasterizeThread::RemoveTask( SvgVisual* renderer )
+void SvgRasterizeThread::RemoveTask( SvgVisual* visual )
{
// Lock while remove task from the queue
ConditionalWait::ScopedLock lock( mConditionalWait );
{
for( std::vector< RasterizingTaskPtr >::iterator it = mRasterizeTasks.begin(), endIt = mRasterizeTasks.end(); it != endIt; ++it )
{
- if( (*it) && (*it)->GetSvgVisual() == renderer )
+ if( (*it) && (*it)->GetSvgVisual() == visual )
{
mRasterizeTasks.erase( it );
break;
}
}
}
+
+ UnregisterProcessor();
}
-void SvgRasterizeThread::DeleteImage( NSVGimage* parsedSvg )
+void SvgRasterizeThread::DeleteImage( VectorImageRenderer vectorRenderer )
{
// Lock while adding image to the delete queue
ConditionalWait::ScopedLock lock( mConditionalWait );
if( mIsThreadWaiting ) // no rasterization is ongoing, save to delete
{
- nsvgDelete( parsedSvg );
+ // TODO: what?
}
else // wait to delete until current rasterization completed.
{
- mDeleteSvg.PushBack( parsedSvg );
+ mDeleteSvg.PushBack( &vectorRenderer );
}
}
// Delete the image here to make sure that it is not used in the nsvgRasterize()
if( !mDeleteSvg.Empty() )
{
- for( Vector< NSVGimage* >::Iterator it = mDeleteSvg.Begin(), endIt = mDeleteSvg.End();
- it != endIt;
- ++it )
- {
- nsvgDelete( *it );
- }
mDeleteSvg.Clear();
}
void SvgRasterizeThread::Run()
{
+ SetThreadName( "SVGThread" );
+ mLogFactory.InstallLogFunction();
+
while( RasterizingTaskPtr task = NextTaskToProcess() )
{
- task->Rasterize( mRasterizer );
+ task->Load( );
+ task->Rasterize( );
AddCompletedTask( task );
}
}
+void SvgRasterizeThread::ApplyRasterizedSVGToSampler()
+{
+ while( RasterizingTaskPtr task = NextCompletedTask() )
+ {
+ task->GetSvgVisual()->ApplyRasterizedImage(task->GetVectorRenderer(), task->GetPixelData(), task->IsLoaded());
+ }
+
+ UnregisterProcessor();
+}
+
+void SvgRasterizeThread::Process()
+{
+ ApplyRasterizedSVGToSampler();
+}
+
+void SvgRasterizeThread::UnregisterProcessor()
+{
+ if ( mProcessorRegistered )
+ {
+ if( mRasterizeTasks.empty() && mCompletedTasks.empty() )
+ {
+ Adaptor::Get().UnregisterProcessor( *this );
+ mProcessorRegistered = false;
+ }
+ }
+}
+
+
} // namespace Internal
} // namespace Toolkit