1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "svg_decoder.h"
17
18 #include <sstream>
19 #include <thread>
20 #include "include/core/SkBitmap.h"
21 #include "include/core/SkCanvas.h"
22 #include "include/core/SkImageInfo.h"
23 #include "image_trace.h"
24 #include "image_log.h"
25 #include "image_utils.h"
26 #include "media_errors.h"
27 #include "securec.h"
28 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
29 #include "surface_buffer.h"
30 #endif
31
32 #undef LOG_DOMAIN
33 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
34
35 #undef LOG_TAG
36 #define LOG_TAG "SvgDecoder"
37
38 namespace OHOS {
39 namespace ImagePlugin {
40 using namespace MultimediaPlugin;
41 using namespace Media;
42 namespace {
43 constexpr uint32_t SVG_IMAGE_NUM = 1;
44 constexpr uint32_t SVG_BYTES_PER_PIXEL = 4;
45 constexpr uint32_t SVG_COLOR_ATTR_WIDTH = 6;
46 constexpr uint32_t SVG_COLOR_MASK = 0xFFFFFF;
47 const std::string SVG_FILL_COLOR_ATTR = "fill";
48 const std::string SVG_STROKE_COLOR_ATTR = "stroke";
49 static constexpr uint32_t DEFAULT_RESIZE_PERCENTAGE = 100;
50 static constexpr float FLOAT_HALF = 0.5f;
51
Float2UInt32(float val)52 static inline uint32_t Float2UInt32(float val)
53 {
54 return static_cast<uint32_t>(val + FLOAT_HALF);
55 }
56
57 #if !defined(_WIN32) && !defined(_APPLE) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
AllocShareBufferInner(DecodeContext & context,uint64_t byteCount)58 bool AllocShareBufferInner(DecodeContext &context, uint64_t byteCount)
59 {
60 uint32_t id = context.pixelmapUniqueId_;
61 std::stringstream sstream;
62 sstream << "SVG RawData, uniqueId: " << std::this_thread::get_id() << '_' << std::to_string(getpid()) <<
63 '_' << std::to_string(id);
64 std::string name = sstream.str();
65 int fd = AshmemCreate(name.c_str(), byteCount);
66 if (fd < 0) {
67 IMAGE_LOGE("[AllocShareBuffer] create fail");
68 return false;
69 }
70
71 int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
72 if (result < 0) {
73 IMAGE_LOGE("[AllocShareBuffer] set fail");
74 ::close(fd);
75 return false;
76 }
77
78 void* ptr = ::mmap(nullptr, byteCount, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
79 if (ptr == MAP_FAILED) {
80 IMAGE_LOGE("[AllocShareBuffer] map fail");
81 ::close(fd);
82 return false;
83 }
84
85 context.pixelsBuffer.buffer = ptr;
86 void *fdBuffer = new int32_t();
87 if (fdBuffer == nullptr) {
88 IMAGE_LOGE("[AllocShareBuffer] new fdBuffer fail");
89 ::munmap(ptr, byteCount);
90 ::close(fd);
91 context.pixelsBuffer.buffer = nullptr;
92 return false;
93 }
94
95 *static_cast<int32_t *>(fdBuffer) = fd;
96 context.pixelsBuffer.context = fdBuffer;
97 context.pixelsBuffer.bufferSize = byteCount;
98 context.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
99 context.freeFunc = nullptr;
100
101 IMAGE_LOGD("[AllocShareBuffer] OUT");
102 return true;
103 }
104 #endif
105
AllocShareBuffer(DecodeContext & context,uint64_t byteCount)106 bool AllocShareBuffer(DecodeContext &context, uint64_t byteCount)
107 {
108 IMAGE_LOGD("[AllocShareBuffer] IN byteCount=%{public}llu",
109 static_cast<unsigned long long>(byteCount));
110
111 if (byteCount > PIXEL_MAP_MAX_RAM_SIZE) {
112 IMAGE_LOGE("[AllocShareBuffer] pixelmap buffer size %{public}llu out of max size",
113 static_cast<unsigned long long>(byteCount));
114 return false;
115 }
116 #if !defined(_WIN32) && !defined(_APPLE) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
117 return AllocShareBufferInner(context, byteCount);
118 #else
119 IMAGE_LOGE("[AllocShareBuffer] Not support Ashmem!");
120 return false;
121 #endif
122 }
123
124 // LCOV_EXCL_START
AllocDmaBuffer(DecodeContext & context,uint64_t byteCount,SkSize & svgSize)125 bool AllocDmaBuffer(DecodeContext &context, uint64_t byteCount, SkSize &svgSize)
126 {
127 IMAGE_LOGD("[AllocDmaBuffer] IN byteCount=%{public}llu",
128 static_cast<unsigned long long>(byteCount));
129
130 if (byteCount > PIXEL_MAP_MAX_RAM_SIZE) {
131 IMAGE_LOGE("[AllocDmaBuffer] pixelmap buffer size %{public}llu out of max size",
132 static_cast<unsigned long long>(byteCount));
133 return false;
134 }
135 #if !defined(_WIN32) && !defined(_APPLE) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
136 sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
137 BufferRequestConfig requestConfig = {
138 .width = svgSize.width(),
139 .height = svgSize.height(),
140 .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
141 .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // PixelFormat
142 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
143 .timeout = 0,
144 .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
145 .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
146 };
147 GSError ret = sb->Alloc(requestConfig);
148 if (ret != GSERROR_OK) {
149 IMAGE_LOGE("SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
150 return false;
151 }
152 void* nativeBuffer = sb.GetRefPtr();
153 int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
154 if (err != OHOS::GSERROR_OK) {
155 IMAGE_LOGE("NativeBufferReference failed");
156 return false;
157 }
158
159 context.pixelsBuffer.buffer = sb->GetVirAddr();
160 context.pixelsBuffer.context = nativeBuffer;
161 context.pixelsBuffer.bufferSize = byteCount;
162 context.allocatorType = AllocatorType::DMA_ALLOC;
163 context.freeFunc = nullptr;
164
165 IMAGE_LOGD("[AllocDmaBuffer] OUT");
166 return true;
167 #else
168 IMAGE_LOGE("[AllocDmaBuffer] Not support dma!");
169 return false;
170 #endif
171 }
172
AllocHeapBuffer(DecodeContext & context,uint64_t byteCount)173 bool AllocHeapBuffer(DecodeContext &context, uint64_t byteCount)
174 {
175 IMAGE_LOGD("[AllocHeapBuffer] IN byteCount=%{public}llu",
176 static_cast<unsigned long long>(byteCount));
177
178 if (byteCount > PIXEL_MAP_MAX_RAM_SIZE) {
179 IMAGE_LOGE("[AllocHeapBuffer] pixelmap buffer size %{public}llu out of max size",
180 static_cast<unsigned long long>(byteCount));
181 return false;
182 }
183
184 auto outputBuffer = malloc(byteCount);
185 if (outputBuffer == nullptr) {
186 IMAGE_LOGE("[AllocHeapBuffer] alloc buffer size:[%{public}llu] failed.",
187 static_cast<unsigned long long>(byteCount));
188 return false;
189 }
190
191 if (memset_s(outputBuffer, byteCount, 0, byteCount) != EOK) {
192 IMAGE_LOGE("[AllocHeapBuffer] memset buffer failed.");
193 free(outputBuffer);
194 outputBuffer = nullptr;
195 return false;
196 }
197
198 context.pixelsBuffer.buffer = outputBuffer;
199 context.pixelsBuffer.bufferSize = byteCount;
200 context.pixelsBuffer.context = nullptr;
201 context.allocatorType = AllocatorType::HEAP_ALLOC;
202 context.freeFunc = nullptr;
203
204 IMAGE_LOGD("[AllocHeapBuffer] OUT");
205 return true;
206 }
207 // LCOV_EXCL_STOP
208
MakeImageInfo(const PixelDecodeOptions & opts)209 SkImageInfo MakeImageInfo(const PixelDecodeOptions &opts)
210 {
211 int width = opts.desiredSize.width;
212 int height = opts.desiredSize.height;
213 SkColorType colorType = SkColorType::kRGBA_8888_SkColorType;
214 SkAlphaType alphaType = SkAlphaType::kPremul_SkAlphaType;
215 return SkImageInfo::Make(width, height, colorType, alphaType);
216 }
217 } // namespace
218
SvgDecoder()219 SvgDecoder::SvgDecoder()
220 {
221 IMAGE_LOGD("[Create] IN");
222
223 IMAGE_LOGD("[Create] OUT");
224 }
225
~SvgDecoder()226 SvgDecoder::~SvgDecoder()
227 {
228 IMAGE_LOGD("[Release] IN");
229
230 Reset();
231
232 IMAGE_LOGD("[Release] OUT");
233 }
234
SetSource(InputDataStream & sourceStream)235 void SvgDecoder::SetSource(InputDataStream &sourceStream)
236 {
237 IMAGE_LOGD("[SetSource] IN");
238
239 Reset();
240
241 inputStreamPtr_ = &sourceStream;
242 state_ = SvgDecodingState::SOURCE_INITED;
243
244 IMAGE_LOGD("[SetSource] OUT");
245 }
246
Reset()247 void SvgDecoder::Reset()
248 {
249 IMAGE_LOGD("[Reset] IN");
250
251 state_ = SvgDecodingState::UNDECIDED;
252
253 if (svgDom_) {
254 svgDom_->setContainerSize(svgSize_);
255 }
256
257 svgDom_ = nullptr;
258 svgStream_ = nullptr;
259 inputStreamPtr_ = nullptr;
260
261 svgSize_.setEmpty();
262
263 PixelDecodeOptions opts;
264 opts_ = opts;
265
266 IMAGE_LOGD("[Reset] OUT");
267 }
268
SetDecodeOptions(uint32_t index,const PixelDecodeOptions & opts,PlImageInfo & info)269 uint32_t SvgDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
270 {
271 if (index >= SVG_IMAGE_NUM) {
272 IMAGE_LOGE("[SetDecodeOptions] decode image index[%{public}u], out of range[%{public}u].",
273 index, SVG_IMAGE_NUM);
274 return Media::ERR_IMAGE_INVALID_PARAMETER;
275 }
276
277 IMAGE_LOGD("[SetDecodeOptions] IN index=%{public}u, pixelFormat=%{public}d, alphaType=%{public}d, "
278 "colorSpace=%{public}d, size=(%{public}u, %{public}u), state=%{public}d", index,
279 static_cast<int32_t>(opts.desiredPixelFormat), static_cast<int32_t>(opts.desireAlphaType),
280 static_cast<int32_t>(opts.desiredColorSpace), opts.desiredSize.width, opts.desiredSize.height, state_);
281
282 if (state_ < SvgDecodingState::SOURCE_INITED) {
283 IMAGE_LOGE("[SetDecodeOptions] set decode options failed for state %{public}d.", state_);
284 return Media::ERR_MEDIA_INVALID_OPERATION;
285 }
286
287 if (state_ >= SvgDecodingState::IMAGE_DECODING) {
288 state_ = SvgDecodingState::SOURCE_INITED;
289 }
290
291 if (state_ < SvgDecodingState::BASE_INFO_PARSED) {
292 uint32_t ret = DoDecodeHeader();
293 if (ret != Media::SUCCESS) {
294 IMAGE_LOGE("[SetDecodeOptions] decode header error on set decode options, ret:%{public}u.", ret);
295 state_ = SvgDecodingState::BASE_INFO_PARSING;
296 return ret;
297 }
298
299 state_ = SvgDecodingState::BASE_INFO_PARSED;
300 }
301
302 // only state SvgDecodingState::BASE_INFO_PARSED can go here.
303 uint32_t ret = DoSetDecodeOptions(index, opts, info);
304 if (ret != Media::SUCCESS) {
305 IMAGE_LOGE("[SetDecodeOptions] do set decode options failed, ret:%{public}u.", ret);
306 state_ = SvgDecodingState::BASE_INFO_PARSING;
307 return ret;
308 }
309
310 state_ = SvgDecodingState::IMAGE_DECODING;
311
312 IMAGE_LOGD("[SetDecodeOptions] OUT");
313 return Media::SUCCESS;
314 }
315
Decode(uint32_t index,DecodeContext & context)316 uint32_t SvgDecoder::Decode(uint32_t index, DecodeContext &context)
317 {
318 ImageTrace imageTrace("SvgDecoder::Decode, index:%u", index);
319 if (index >= SVG_IMAGE_NUM) {
320 IMAGE_LOGE("[Decode] decode image index[%{public}u], out of range[%{public}u].",
321 index, SVG_IMAGE_NUM);
322 return Media::ERR_IMAGE_INVALID_PARAMETER;
323 }
324
325 IMAGE_LOGD("[Decode] IN index=%{public}u", index);
326
327 if (state_ < SvgDecodingState::IMAGE_DECODING) {
328 IMAGE_LOGE("[Decode] decode failed for state %{public}d.", state_);
329 return Media::ERR_MEDIA_INVALID_OPERATION;
330 }
331
332 uint32_t ret = DoDecode(index, context);
333 if (ret == Media::SUCCESS) {
334 IMAGE_LOGD("[Decode] success.");
335 state_ = SvgDecodingState::IMAGE_DECODED;
336 } else {
337 IMAGE_LOGE("[Decode] fail, ret=%{public}u", ret);
338 state_ = SvgDecodingState::IMAGE_ERROR;
339 }
340
341 IMAGE_LOGD("[Decode] OUT ret=%{public}u", ret);
342 return ret;
343 }
344
PromoteIncrementalDecode(uint32_t index,ProgDecodeContext & context)345 uint32_t SvgDecoder::PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &context)
346 {
347 // currently not support increment decode
348 return ERR_IMAGE_DATA_UNSUPPORT;
349 }
350
351 // need decode all frame to get total number.
GetTopLevelImageNum(uint32_t & num)352 uint32_t SvgDecoder::GetTopLevelImageNum(uint32_t &num)
353 {
354 num = SVG_IMAGE_NUM;
355 return Media::SUCCESS;
356 }
357
358 // return background size but not specific frame size, cause of frame drawing on background.
GetImageSize(uint32_t index,Size & size)359 uint32_t SvgDecoder::GetImageSize(uint32_t index, Size &size)
360 {
361 if (index >= SVG_IMAGE_NUM) {
362 IMAGE_LOGE("[GetImageSize] decode image index[%{public}u], out of range[%{public}u].",
363 index, SVG_IMAGE_NUM);
364 return Media::ERR_IMAGE_INVALID_PARAMETER;
365 }
366
367 IMAGE_LOGD("[GetImageSize] IN index=%{public}u", index);
368
369 if (state_ < SvgDecodingState::SOURCE_INITED) {
370 IMAGE_LOGE("[GetImageSize] get image size failed for state %{public}d.", state_);
371 return ERR_MEDIA_INVALID_OPERATION;
372 }
373
374 if (state_ >= SvgDecodingState::BASE_INFO_PARSED) {
375 DoGetImageSize(index, size);
376 IMAGE_LOGD("[GetImageSize] OUT size=(%{public}u, %{public}u)", size.width, size.height);
377 return Media::SUCCESS;
378 }
379
380 // only state SvgDecodingState::SOURCE_INITED and SvgDecodingState::BASE_INFO_PARSING can go here.
381 uint32_t ret = DoDecodeHeader();
382 if (ret != Media::SUCCESS) {
383 IMAGE_LOGE("[GetImageSize] decode header error on get image size, ret:%{public}u.", ret);
384 state_ = SvgDecodingState::BASE_INFO_PARSING;
385 return ret;
386 }
387
388 ret = DoGetImageSize(index, size);
389 if (ret != Media::SUCCESS) {
390 IMAGE_LOGE("[GetImageSize] do get image size failed, ret:%{public}u.", ret);
391 state_ = SvgDecodingState::BASE_INFO_PARSING;
392 return ret;
393 }
394
395 state_ = SvgDecodingState::BASE_INFO_PARSED;
396
397 IMAGE_LOGD("[GetImageSize] OUT size=(%{public}u, %{public}u)", size.width, size.height);
398 return Media::SUCCESS;
399 }
400
AllocBuffer(DecodeContext & context)401 bool SvgDecoder::AllocBuffer(DecodeContext &context)
402 {
403 IMAGE_LOGD("[AllocBuffer] IN");
404
405 if (svgDom_ == nullptr) {
406 IMAGE_LOGE("[AllocBuffer] DOM is null.");
407 return false;
408 }
409
410 bool ret = true;
411 if (context.pixelsBuffer.buffer == nullptr) {
412 auto svgSize = svgDom_->containerSize();
413 if (svgSize.isEmpty()) {
414 IMAGE_LOGE("[AllocBuffer] size is empty.");
415 return false;
416 }
417 uint32_t width = Float2UInt32(svgSize.width());
418 uint32_t height = Float2UInt32(svgSize.height());
419 uint64_t byteCount = static_cast<uint64_t>(width) * height * SVG_BYTES_PER_PIXEL;
420 if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
421 ret = AllocShareBuffer(context, byteCount);
422 } else if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
423 ret = AllocDmaBuffer(context, byteCount, svgSize);
424 } else {
425 ret = AllocHeapBuffer(context, byteCount);
426 }
427 }
428
429 IMAGE_LOGD("[AllocBuffer] OUT ret=%{public}d", ret);
430 return ret;
431 }
432
BuildStream()433 bool SvgDecoder::BuildStream()
434 {
435 IMAGE_LOGD("[BuildStream] IN");
436
437 if (inputStreamPtr_ == nullptr) {
438 IMAGE_LOGE("[BuildStream] Stream is null.");
439 return false;
440 }
441
442 auto length = inputStreamPtr_->GetStreamSize();
443 if (inputStreamPtr_->GetStreamType() == ImagePlugin::BUFFER_SOURCE_TYPE) {
444 svgStream_ = std::make_unique<SkMemoryStream>(inputStreamPtr_->GetDataPtr(), length);
445 } else {
446 auto data = std::make_unique<uint8_t[]>(length);
447 uint32_t readSize = 0;
448 if (!inputStreamPtr_->Read(length, data.get(), length, readSize)) {
449 IMAGE_LOGE("[BuildStream] read failed.");
450 return false;
451 }
452 svgStream_ = std::make_unique<SkMemoryStream>(data.get(), length, true);
453 }
454
455 IMAGE_LOGD("[BuildStream] OUT");
456 return true;
457 }
458
SetSVGColor(SkSVGNode * node,std::string color,std::string colorAttr)459 static void SetSVGColor(SkSVGNode* node, std::string color, std::string colorAttr)
460 {
461 if (node == nullptr) {
462 return;
463 }
464 IMAGE_LOGD("[SetSVGColor] node tag %{public}d %{public}s %{public}s.",
465 node->tag(), color.c_str(), colorAttr.c_str());
466 node->setAttribute(colorAttr.c_str(), color.c_str());
467 for (auto childNode : node->getChild()) {
468 SetSVGColor(childNode.get(), color, colorAttr);
469 }
470 }
471
SetSVGColor(SkSVGNode * node,uint32_t color,std::string colorAttr)472 static void SetSVGColor(SkSVGNode* node, uint32_t color, std::string colorAttr)
473 {
474 std::stringstream stream;
475 stream.fill('0');
476 stream.width(SVG_COLOR_ATTR_WIDTH);
477 stream << std::hex << (color & SVG_COLOR_MASK);
478 std::string newValue(stream.str());
479 SetSVGColor(node, "#" + newValue, colorAttr);
480 }
481
BuildDom()482 bool SvgDecoder::BuildDom()
483 {
484 IMAGE_LOGD("[BuildDom] IN");
485
486 if (svgStream_ == nullptr) {
487 IMAGE_LOGE("[BuildDom] Stream is null.");
488 return false;
489 }
490
491 svgDom_ = SkSVGDOM::MakeFromStream(*(svgStream_.get()));
492 if (svgDom_ == nullptr) {
493 IMAGE_LOGE("[BuildDom] DOM is null.");
494 return false;
495 }
496
497 svgSize_ = svgDom_->containerSize();
498 if (svgSize_.isEmpty()) {
499 IMAGE_LOGE("[BuildDom] size is empty.");
500 return false;
501 }
502
503 auto width = Float2UInt32(svgSize_.width());
504 auto height = Float2UInt32(svgSize_.height());
505
506 IMAGE_LOGD("[BuildDom] OUT size=(%{public}u, %{public}u)", width, height);
507 return true;
508 }
509
DoDecodeHeader()510 uint32_t SvgDecoder::DoDecodeHeader()
511 {
512 IMAGE_LOGD("[DoDecodeHeader] IN");
513
514 if (!BuildStream()) {
515 IMAGE_LOGE("[DoDecodeHeader] Build Stream failed");
516 return Media::ERR_IMAGE_TOO_LARGE;
517 }
518
519 if (!BuildDom()) {
520 IMAGE_LOGE("[DoDecodeHeader] Build DOM failed");
521 return Media::ERR_IMAGE_DATA_UNSUPPORT;
522 }
523
524 IMAGE_LOGD("[DoDecodeHeader] OUT");
525 return Media::SUCCESS;
526 }
527
DoSetDecodeOptions(uint32_t index,const PixelDecodeOptions & opts,PlImageInfo & info)528 uint32_t SvgDecoder::DoSetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
529 {
530 IMAGE_LOGD("[DoSetDecodeOptions] IN index=%{public}u", index);
531
532 if (svgDom_ == nullptr) {
533 IMAGE_LOGE("[DoSetDecodeOptions] DOM is null.");
534 return Media::ERROR;
535 }
536
537 opts_ = opts;
538
539 auto svgSize = svgDom_->containerSize();
540 if (svgSize.isEmpty()) {
541 IMAGE_LOGE("[DoSetDecodeOptions] size is empty.");
542 return Media::ERROR;
543 }
544
545 float scaleFitDesired = 1.0;
546 if (opts_.desiredSize.width && opts_.desiredSize.height) {
547 scaleFitDesired = std::min(static_cast<float>(opts_.desiredSize.width) / svgSize.width(),
548 static_cast<float>(opts_.desiredSize.height) / svgSize.height());
549 }
550
551 if (opts_.plSVGResize.isValidPercentage) {
552 svgDom_->setResizePercentage(opts_.plSVGResize.resizePercentage * scaleFitDesired);
553 } else {
554 svgDom_->setResizePercentage(DEFAULT_RESIZE_PERCENTAGE * scaleFitDesired);
555 }
556
557 opts_.desiredSize.width = static_cast<int32_t>(Float2UInt32(svgDom_->containerSize().width()));
558 opts_.desiredSize.height = static_cast<int32_t>(Float2UInt32(svgDom_->containerSize().height()));
559
560 info.size.width = opts_.desiredSize.width;
561 info.size.height = opts_.desiredSize.height;
562 info.pixelFormat = PixelFormat::RGBA_8888;
563 info.colorSpace = ColorSpace::UNKNOWN;
564 info.alphaType = AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
565
566 IMAGE_LOGD("[DoSetDecodeOptions] OUT pixelFormat=%{public}d, alphaType=%{public}d, "
567 "colorSpace=%{public}d, size=(%{public}u, %{public}u)",
568 static_cast<int32_t>(info.pixelFormat), static_cast<int32_t>(info.alphaType),
569 static_cast<int32_t>(info.colorSpace), info.size.width, info.size.height);
570 return Media::SUCCESS;
571 }
572
DoGetImageSize(uint32_t index,Size & size)573 uint32_t SvgDecoder::DoGetImageSize(uint32_t index, Size &size)
574 {
575 IMAGE_LOGD("[DoGetImageSize] IN index=%{public}u", index);
576
577 if (svgDom_ == nullptr) {
578 IMAGE_LOGE("[DoGetImageSize] DOM is null.");
579 return Media::ERROR;
580 }
581
582 auto svgSize = svgDom_->containerSize();
583 if (svgSize.isEmpty()) {
584 IMAGE_LOGE("[DoGetImageSize] size is empty.");
585 return Media::ERROR;
586 }
587
588 size.width = static_cast<int32_t>(Float2UInt32(svgSize.width()));
589 size.height = static_cast<int32_t>(Float2UInt32(svgSize.height()));
590
591 IMAGE_LOGD("[DoGetImageSize] OUT size=(%{public}u, %{public}u)", size.width, size.height);
592 return Media::SUCCESS;
593 }
594
DoDecode(uint32_t index,DecodeContext & context)595 uint32_t SvgDecoder::DoDecode(uint32_t index, DecodeContext &context)
596 {
597 IMAGE_LOGD("[DoDecode] IN index=%{public}u", index);
598
599 if (svgDom_ == nullptr) {
600 IMAGE_LOGE("[DoDecode] DOM is null.");
601 return Media::ERROR;
602 }
603
604 if (opts_.plFillColor.isValidColor) {
605 SetSVGColor(svgDom_->getRoot(), opts_.plFillColor.color, SVG_FILL_COLOR_ATTR);
606 }
607
608 if (opts_.plStrokeColor.isValidColor) {
609 SetSVGColor(svgDom_->getRoot(), opts_.plStrokeColor.color, SVG_STROKE_COLOR_ATTR);
610 }
611
612 if (!AllocBuffer(context)) {
613 IMAGE_LOGE("[DoDecode] alloc buffer failed.");
614 return Media::ERR_IMAGE_MALLOC_ABNORMAL;
615 }
616
617 auto imageInfo = MakeImageInfo(opts_);
618 auto rowBytes = static_cast<uint32_t>(opts_.desiredSize.width * SVG_BYTES_PER_PIXEL);
619 auto pixels = context.pixelsBuffer.buffer;
620
621 SkBitmap bitmap;
622 if (!bitmap.installPixels(imageInfo, pixels, rowBytes)) {
623 IMAGE_LOGE("[DoDecode] bitmap install pixels failed.");
624 return Media::ERROR;
625 }
626
627 auto canvas = SkCanvas::MakeRasterDirect(imageInfo, bitmap.getPixels(), bitmap.rowBytes());
628 if (canvas == nullptr) {
629 IMAGE_LOGE("[DoDecode] make canvas failed.");
630 return Media::ERROR;
631 }
632 canvas->clear(SK_ColorTRANSPARENT);
633 svgDom_->render(canvas.get());
634
635 bool result = canvas->readPixels(imageInfo, pixels, rowBytes, 0, 0);
636 if (!result) {
637 IMAGE_LOGE("[DoDecode] read pixels failed.");
638 return Media::ERROR;
639 }
640
641 IMAGE_LOGD("[DoDecode] OUT");
642 ImageUtils::FlushContextSurfaceBuffer(context);
643 return Media::SUCCESS;
644 }
645 } // namespace ImagePlugin
646 } // namespace OHOS