2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "svg-rasterize-thread.h"
22 #include <dali/devel-api/adaptor-framework/file-loader.h>
23 #include <dali/devel-api/adaptor-framework/thread-settings.h>
24 #include <dali/integration-api/adaptor-framework/adaptor.h>
25 #include <dali/integration-api/debug.h>
28 #include <dali-toolkit/internal/visuals/svg/svg-visual.h>
36 RasterizingTask::RasterizingTask(SvgVisual* svgVisual, VectorImageRenderer vectorRenderer, const VisualUrl& url, float dpi, unsigned int width, unsigned int height)
37 : mSvgVisual(svgVisual),
38 mVectorRenderer(vectorRenderer),
47 RasterizingTask::~RasterizingTask()
51 void RasterizingTask::Load()
53 if(mVectorRenderer.IsLoaded())
60 Dali::Vector<uint8_t> buffer;
62 if(!mUrl.IsLocalResource())
64 if(!Dali::FileLoader::DownloadFileSynchronously(mUrl.GetUrl(), buffer))
66 DALI_LOG_ERROR("Failed to download file! [%s]\n", mUrl.GetUrl().c_str());
72 if(!Dali::FileLoader::ReadFile(mUrl.GetUrl(), buffer))
74 DALI_LOG_ERROR("Failed to read file! [%s]\n", mUrl.GetUrl().c_str());
79 buffer.PushBack('\0');
81 if(!mVectorRenderer.Load(buffer, mDpi))
83 DALI_LOG_ERROR("Failed to load data! [%s]\n", mUrl.GetUrl().c_str());
90 void RasterizingTask::Rasterize()
92 Devel::PixelBuffer pixelBuffer = mVectorRenderer.Rasterize(mWidth, mHeight);
95 DALI_LOG_ERROR("Rasterize is failed! [%s]\n", mUrl.GetUrl().c_str());
99 mPixelData = Devel::PixelBuffer::Convert(pixelBuffer);
102 bool RasterizingTask::IsLoaded() const
107 SvgVisual* RasterizingTask::GetSvgVisual() const
109 return mSvgVisual.Get();
112 PixelData RasterizingTask::GetPixelData() const
117 SvgRasterizeThread::SvgRasterizeThread()
118 : mTrigger(new EventThreadCallback(MakeCallback(this, &SvgRasterizeThread::ApplyRasterizedSVGToSampler))),
119 mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
120 mIsThreadWaiting(false),
121 mProcessorRegistered(false)
125 SvgRasterizeThread::~SvgRasterizeThread()
127 if(mProcessorRegistered)
129 Adaptor::Get().UnregisterProcessor(*this);
133 void SvgRasterizeThread::TerminateThread(SvgRasterizeThread*& thread)
137 // add an empty task would stop the thread from conditional wait.
138 thread->AddTask(RasterizingTaskPtr());
147 void SvgRasterizeThread::AddTask(RasterizingTaskPtr task)
149 bool wasEmpty = false;
152 // Lock while adding task to the queue
153 ConditionalWait::ScopedLock lock(mConditionalWait);
154 wasEmpty = mRasterizeTasks.empty();
155 if(!wasEmpty && task)
157 // Remove the tasks with the same renderer.
158 // Older task which waiting to rasterize and apply the svg to the same renderer is expired.
159 for(std::vector<RasterizingTaskPtr>::iterator it = mRasterizeTasks.begin(), endIt = mRasterizeTasks.end(); it != endIt; ++it)
161 if((*it) && (*it)->GetSvgVisual() == task->GetSvgVisual())
163 mRasterizeTasks.erase(it);
168 mRasterizeTasks.push_back(task);
170 if(!mProcessorRegistered)
172 Adaptor::Get().RegisterProcessor(*this);
173 mProcessorRegistered = true;
179 // wake up the image loading thread
180 mConditionalWait.Notify();
184 RasterizingTaskPtr SvgRasterizeThread::NextCompletedTask()
186 // Lock while popping task out from the queue
187 Mutex::ScopedLock lock(mMutex);
189 if(mCompletedTasks.empty())
191 return RasterizingTaskPtr();
194 std::vector<RasterizingTaskPtr>::iterator next = mCompletedTasks.begin();
195 RasterizingTaskPtr nextTask = *next;
196 mCompletedTasks.erase(next);
201 void SvgRasterizeThread::RemoveTask(SvgVisual* visual)
203 // Lock while remove task from the queue
204 ConditionalWait::ScopedLock lock(mConditionalWait);
205 if(!mRasterizeTasks.empty())
207 for(std::vector<RasterizingTaskPtr>::iterator it = mRasterizeTasks.begin(), endIt = mRasterizeTasks.end(); it != endIt; ++it)
209 if((*it) && (*it)->GetSvgVisual() == visual)
211 mRasterizeTasks.erase(it);
217 UnregisterProcessor();
220 RasterizingTaskPtr SvgRasterizeThread::NextTaskToProcess()
222 // Lock while popping task out from the queue
223 ConditionalWait::ScopedLock lock(mConditionalWait);
226 while(mRasterizeTasks.empty())
228 mIsThreadWaiting = true;
229 mConditionalWait.Wait(lock);
231 mIsThreadWaiting = false;
233 // pop out the next task from the queue
234 std::vector<RasterizingTaskPtr>::iterator next = mRasterizeTasks.begin();
235 RasterizingTaskPtr nextTask = *next;
236 mRasterizeTasks.erase(next);
241 void SvgRasterizeThread::AddCompletedTask(RasterizingTaskPtr task)
243 // Lock while adding task to the queue
244 Mutex::ScopedLock lock(mMutex);
245 mCompletedTasks.push_back(task);
247 // wake up the main thread
251 void SvgRasterizeThread::Run()
253 SetThreadName("SVGThread");
254 mLogFactory.InstallLogFunction();
256 while(RasterizingTaskPtr task = NextTaskToProcess())
260 AddCompletedTask(task);
264 void SvgRasterizeThread::ApplyRasterizedSVGToSampler()
266 while(RasterizingTaskPtr task = NextCompletedTask())
268 task->GetSvgVisual()->ApplyRasterizedImage(task->GetPixelData(), task->IsLoaded());
271 UnregisterProcessor();
274 void SvgRasterizeThread::Process(bool postProcessor)
276 ApplyRasterizedSVGToSampler();
279 void SvgRasterizeThread::UnregisterProcessor()
281 if(mProcessorRegistered)
283 if(mRasterizeTasks.empty() && mCompletedTasks.empty())
285 Adaptor::Get().UnregisterProcessor(*this);
286 mProcessorRegistered = false;
291 } // namespace Internal
293 } // namespace Toolkit