2 * Copyright (c) 2023 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 <dali/internal/vector-image/common/vector-image-renderer-impl.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/object/type-registry.h>
25 #ifndef THORVG_SUPPORT
27 #include <third-party/nanosvg/nanosvg.h>
28 #include <third-party/nanosvg/nanosvgrast.h>
37 namespace // unnamed namespace
39 const char* const UNITS("px");
42 Dali::BaseHandle Create()
44 return Dali::BaseHandle();
47 Dali::TypeRegistration type(typeid(Dali::VectorImageRenderer), typeid(Dali::BaseHandle), Create);
49 #if defined(DEBUG_ENABLED)
50 Debug::Filter* gVectorImageLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VECTOR_IMAGE");
53 } // unnamed namespace
55 VectorImageRendererPtr VectorImageRenderer::New()
57 VectorImageRendererPtr renderer = new VectorImageRenderer();
60 renderer->Initialize();
65 VectorImageRenderer::VectorImageRenderer()
69 : mParsedImage(nullptr),
75 VectorImageRenderer::~VectorImageRenderer()
77 Mutex::ScopedLock lock(mMutex);
80 //NOTE: Initializer::term() will call clear() internally.
81 //However, due to the delete on mPicture, a crash occurs for the paint
82 //that has already been deleted in clear() of term().
83 //Therefore, it temporarily performs a non-free clear().
84 mSwCanvas->clear(false);
92 tvg::Initializer::term(tvg::CanvasEngine::Sw);
96 nsvgDelete(mParsedImage);
97 mParsedImage = nullptr;
102 nsvgDeleteRasterizer(mRasterizer);
103 mRasterizer = nullptr;
108 void VectorImageRenderer::Initialize()
110 #ifdef THORVG_SUPPORT
111 tvg::Initializer::init(tvg::CanvasEngine::Sw, 0);
113 mSwCanvas = tvg::SwCanvas::gen();
114 mSwCanvas->mempool(tvg::SwCanvas::MempoolPolicy::Individual);
115 mSwCanvas->reserve(1); //has one picture
117 mRasterizer = nsvgCreateRasterizer();
121 bool VectorImageRenderer::Load(const Vector<uint8_t>& data, float dpi)
123 Mutex::ScopedLock lock(mMutex);
125 #ifdef THORVG_SUPPORT
128 DALI_LOG_ERROR("VectorImageRenderer::Load Canvas Object is null [%p]\n", this);
134 mPicture = tvg::Picture::gen().release();
137 DALI_LOG_ERROR("VectorImageRenderer::Load: Picture gen Fail [%p]\n", this);
146 tvg::Result ret = mPicture->load(reinterpret_cast<char*>(data.Begin()), data.Size(), true);
148 if(ret != tvg::Result::Success)
152 case tvg::Result::InvalidArguments:
154 DALI_LOG_ERROR("VectorImageRenderer::Load Load fail(Invalid arguments) Size:%d [%p]\n", data.Size(), this);
157 case tvg::Result::NonSupport:
159 DALI_LOG_ERROR("VectorImageRenderer::Load Load fail(Invalid SVG) Size:%d [%p]\n", data.Size(), this);
162 case tvg::Result::Unknown:
164 DALI_LOG_ERROR("VectorImageRenderer::Load Load fail(Parse fail) Size:%d [%p]\n", data.Size(), this);
169 DALI_LOG_ERROR("VectorImageRenderer::Load Load fail / Size:%d [%p]\n", data.Size(), this);
174 // Destroy mPicture and make it as nullptr, so we can notify that we fail to load svg file.
185 mPicture->size(&w, &h);
186 mDefaultWidth = static_cast<uint32_t>(w);
187 mDefaultHeight = static_cast<uint32_t>(h);
196 mParsedImage = nsvgParse(reinterpret_cast<char*>(data.Begin()), UNITS, dpi);
197 if(!mParsedImage || !mParsedImage->shapes)
199 DALI_LOG_ERROR("VectorImageRenderer::Load: nsvgParse failed\n");
201 // Destroy mParsedImage and make it as nullptr, so we can notify that we fail to load svg file.
204 nsvgDelete(mParsedImage);
205 mParsedImage = nullptr;
211 mDefaultWidth = mParsedImage->width;
212 mDefaultHeight = mParsedImage->height;
218 bool VectorImageRenderer::IsLoaded() const
220 #ifdef THORVG_SUPPORT
221 return mPicture ? true : false;
223 return mParsedImage ? true : false;
227 Dali::Devel::PixelBuffer VectorImageRenderer::Rasterize(uint32_t width, uint32_t height)
229 Mutex::ScopedLock lock(mMutex);
233 if(mDefaultWidth == 0)
235 DALI_LOG_ERROR("Invalid size [%d, %d]\n", width, height);
236 return Devel::PixelBuffer();
240 width = mDefaultWidth;
246 if(mDefaultHeight == 0)
248 DALI_LOG_ERROR("Invalid size [%d, %d]\n", width, height);
249 return Devel::PixelBuffer();
253 height = mDefaultHeight;
257 #ifdef THORVG_SUPPORT
258 if(!mSwCanvas || !mPicture)
260 DALI_LOG_ERROR("VectorImageRenderer::Rasterize: either Canvas[%p] or Picture[%p] is invalid [%p]\n", mSwCanvas.get(), mPicture, this);
261 return Devel::PixelBuffer();
264 Devel::PixelBuffer pixelBuffer = Devel::PixelBuffer::New(width, height, Dali::Pixel::RGBA8888);
266 mSwCanvas->clear(false);
268 auto pBuffer = pixelBuffer.GetBuffer();
271 DALI_LOG_ERROR("VectorImageRenderer::Rasterize: pixel buffer is null [%p]\n", this);
272 return Devel::PixelBuffer();
275 mSwCanvas->target(reinterpret_cast<uint32_t*>(pBuffer), width, width, height, tvg::SwCanvas::ABGR8888);
277 DALI_LOG_INFO(gVectorImageLogFilter, Debug::Verbose, "Buffer[%p] size[%d x %d]! [%p]\n", pBuffer, width, height, this);
279 mPicture->size(width, height);
281 /* We can push everytime since we cleared the canvas just before. */
282 if(mSwCanvas->push(std::unique_ptr<tvg::Picture>(mPicture)) != tvg::Result::Success)
284 DALI_LOG_ERROR("VectorImageRenderer::Rasterize: Picture push fail [%p]\n", this);
285 return Devel::PixelBuffer();
288 auto ret = mSwCanvas->draw();
289 if(ret != tvg::Result::Success)
291 DALI_LOG_ERROR("VectorImageRenderer::Rasterize: Draw fail %d [%p]\n", static_cast<int>(ret), this);
292 return Devel::PixelBuffer();
299 if(mParsedImage != nullptr)
301 Devel::PixelBuffer pixelBuffer = Devel::PixelBuffer::New(width, height, Dali::Pixel::RGBA8888);
303 float scaleX = static_cast<float>(width) / (mDefaultWidth > 0 ? static_cast<float>(mDefaultWidth) : 1.0f);
304 float scaleY = static_cast<float>(height) / (mDefaultHeight > 0 ? static_cast<float>(mDefaultHeight) : 1.0f);
305 float scale = scaleX < scaleY ? scaleX : scaleY;
306 int stride = pixelBuffer.GetWidth() * Pixel::GetBytesPerPixel(Dali::Pixel::RGBA8888);
308 nsvgRasterize(mRasterizer, mParsedImage, 0.0f, 0.0f, scale, pixelBuffer.GetBuffer(), width, height, stride);
311 return Devel::PixelBuffer();
315 void VectorImageRenderer::GetDefaultSize(uint32_t& width, uint32_t& height) const
317 width = mDefaultWidth;
318 height = mDefaultHeight;
321 } // namespace Adaptor
323 } // namespace Internal