/*
- * 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.
// 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
{
-
-namespace
+RasterizingTask::RasterizingTask(SvgVisual* svgRenderer, VectorImageRenderer vectorRenderer, const VisualUrl& url, float dpi, unsigned int width, unsigned int height)
+: mSvgVisual(svgRenderer),
+ mVectorRenderer(vectorRenderer),
+ mUrl(url),
+ mDpi(dpi),
+ mWidth(width),
+ mHeight(height),
+ mLoadSuccess(false)
{
-const char * const UNITS("px");
-}
-RasterizingTask::RasterizingTask( SvgVisual* svgRenderer, NSVGimage* parsedSvg, const VisualUrl& url, float dpi, unsigned int width, unsigned int height)
-: mSvgVisual( svgRenderer ),
- mParsedSvg( parsedSvg ),
- mUrl( url ),
- mDpi( dpi ),
- mWidth( width ),
- mHeight( height )
-{
- mRasterizer = nsvgCreateRasterizer();
}
RasterizingTask::~RasterizingTask()
{
- nsvgDeleteRasterizer( mRasterizer );
}
void RasterizingTask::Load()
{
- if( mParsedSvg != NULL)
- {
- return;
- }
-
- if( !mUrl.IsLocalResource() )
+ if(!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;
+ }
- if( !Dali::FileLoader::DownloadFileSynchronously( mUrl.GetUrl(), remoteBuffer ))
+ remoteBuffer.PushBack('\0');
+
+ if(!mVectorRenderer.Load(remoteBuffer, mDpi))
{
- DALI_LOG_ERROR("Failed to download file!\n");
+ DALI_LOG_ERROR("RasterizingTask::Load:Failed to load data! [%s]\n", mUrl.GetUrl().c_str());
return;
}
- remoteBuffer.PushBack( '\0' );
- mParsedSvg = nsvgParse( reinterpret_cast<char*>(remoteBuffer.begin()), UNITS, mDpi );
+ mLoadSuccess = true;
+ }
+ else
+ {
+ mLoadSuccess = true;
}
}
-void RasterizingTask::Rasterize( )
+void RasterizingTask::Rasterize()
{
- if( mParsedSvg != NULL && 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;
-
- unsigned char* buffer = new unsigned char [bufferSize];
- nsvgRasterize(mRasterizer, mParsedSvg, 0.f,0.f,scale,
- buffer, mWidth, mHeight,
- bufferStride );
-
- mPixelData = Dali::PixelData::New( buffer, bufferSize, mWidth, mHeight, Pixel::RGBA8888, Dali::PixelData::DELETE_ARRAY );
+ DALI_LOG_ERROR("RasterizingTask::Rasterize: Size is zero!\n");
+ return;
}
+
+ Devel::PixelBuffer pixelBuffer = Devel::PixelBuffer::New(mWidth, mHeight, Dali::Pixel::RGBA8888);
+
+ 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;
}
-NSVGimage* RasterizingTask::GetParsedImage() const
+bool RasterizingTask::IsLoaded() const
{
- return mParsedSvg;
+ return mLoadSuccess;
}
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 )
{
}
SvgRasterizeThread::~SvgRasterizeThread()
{
- 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)
}
}
}
+
+ 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->Load( );
}
}
+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