1 /*
2 * Copyright (c) 2021-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 "core/components/image/rosen_render_image.h"
17
18 #ifndef USE_ROSEN_DRAWING
19 #include "include/core/SkClipOp.h"
20 #include "include/core/SkColorFilter.h"
21 #include "include/core/SkRect.h"
22 #include "include/core/SkShader.h"
23 #else
24 #include "drawing/engine_adapter/skia_adapter/skia_data.h"
25 #endif
26
27 #include "base/thread/background_task_executor.h"
28 #include "core/components/text_overlay/text_overlay_component.h"
29 #ifndef USE_ROSEN_DRAWING
30 #include "core/components_ng/render/adapter/skia_image.h"
31 #else
32 #include "core/components_ng/render/adapter/rosen/drawing_image.h"
33 #endif
34 #include "core/image/image_object.h"
35 #include "core/pipeline/base/rosen_render_context.h"
36
37 namespace OHOS::Ace {
38 namespace {
39 // The [GRAY_COLOR_MATRIX] is of dimension [4 x 5], which transforms a RGB source color (R, G, B, A) to the
40 // destination color (R', G', B', A').
41 //
42 // A classic color image to grayscale conversion formula is [Gray = R * 0.3 + G * 0.59 + B * 0.11].
43 // Hence we get the following conversion:
44 //
45 // | M11 M12 M13 M14 M15 | | R | | R' |
46 // | M21 M22 M23 M24 M25 | | G | | G' |
47 // | M31 M32 M33 M34 M35 | x | B | = | B' |
48 // | M41 M42 M43 M44 M45 | | A | | A' |
49 // | 1 |
50 const float GRAY_COLOR_MATRIX[20] = { 0.30f, 0.59f, 0.11f, 0, 0, // red
51 0.30f, 0.59f, 0.11f, 0, 0, // green
52 0.30f, 0.59f, 0.11f, 0, 0, // blue
53 0, 0, 0, 1.0f, 0 }; // alpha transparency
54
55 #ifdef USE_ROSEN_DRAWING
56 constexpr float FLOAT_HALF = 0.5f;
57 #endif
58 } // namespace
59
60 #ifndef USE_ROSEN_DRAWING
61 union SkColorEx {
62 struct {
63 SkColor color : 32;
64 bool valid : 1;
65 uint32_t reserved : 31; // reserved
66 };
67 uint64_t value = 0;
68 };
69 #else
70 union DrawingColorEx {
71 struct {
72 RSColorQuad color : 32;
73 bool valid : 1;
74 uint32_t reserved : 31; // reserved
75 };
76 uint64_t value = 0;
77 };
78 #endif
79
RosenRenderImage()80 RosenRenderImage::RosenRenderImage()
81 {
82 InitializeCallbacks();
83 }
84
~RosenRenderImage()85 RosenRenderImage::~RosenRenderImage()
86 {
87 CancelBackgroundTasks();
88 }
89
InitializeCallbacks()90 void RosenRenderImage::InitializeCallbacks()
91 {
92 imageObjSuccessCallback_ = [weak = AceType::WeakClaim(this)](
93 ImageSourceInfo info, const RefPtr<ImageObject>& imageObj) {
94 auto renderImage = weak.Upgrade();
95 if (!renderImage) {
96 return;
97 }
98 if (renderImage->sourceInfo_ == info) {
99 renderImage->ImageObjReady(imageObj);
100 return;
101 }
102 LOGW("imageObjSuccessCallback: image source info verify fail. sourceInfo: %{private}s, "
103 "callback source info: %{private}s",
104 renderImage->sourceInfo_.ToString().c_str(), info.ToString().c_str());
105 };
106
107 failedCallback_ = [weak = AceType::WeakClaim(this)](ImageSourceInfo info, const std::string& errorMsg) {
108 auto renderImage = weak.Upgrade();
109 if (!renderImage) {
110 return;
111 }
112 if (info != renderImage->sourceInfo_) {
113 return;
114 }
115 auto context = renderImage->GetContext().Upgrade();
116 if (!context) {
117 return;
118 }
119 auto isDeclarative = context->GetIsDeclarative();
120 if (!isDeclarative && !renderImage->syncMode_ && renderImage->RetryLoading()) {
121 LOGI("retry loading. sourceInfo: %{private}s", renderImage->sourceInfo_.ToString().c_str());
122 return;
123 }
124 renderImage->ImageObjFailed(errorMsg);
125 };
126 uploadSuccessCallback_ = [weak = AceType::WeakClaim(this)](
127 ImageSourceInfo sourceInfo, const RefPtr<NG::CanvasImage>& image) {
128 auto renderImage = weak.Upgrade();
129 if (!renderImage) {
130 return;
131 }
132 if (renderImage->sourceInfo_ == sourceInfo) {
133 renderImage->ImageDataPaintSuccess(image);
134 return;
135 }
136 LOGW("paintDataSuccessCallback: image source info verify fail. sourceInfo: %{private}s, callback source info: "
137 "%{private}s",
138 renderImage->sourceInfo_.ToString().c_str(), sourceInfo.ToString().c_str());
139 };
140
141 onPostBackgroundTask_ = [weak = AceType::WeakClaim(this)](CancelableTask task) {
142 auto renderImage = weak.Upgrade();
143 if (renderImage) {
144 renderImage->SetFetchImageObjBackgroundTask(task);
145 }
146 };
147 }
148
ImageObjReady(const RefPtr<ImageObject> & imageObj)149 void RosenRenderImage::ImageObjReady(const RefPtr<ImageObject>& imageObj)
150 {
151 if (!Container::Current()) {
152 return;
153 }
154 CHECK_NULL_VOID(imageObj);
155 imageObj_ = imageObj;
156 auto imageSize = imageObj_->GetImageSize();
157 bool canStartUploadImageObj = !autoResize_ && (imageObj_->GetFrameCount() == 1);
158 if (canStartUploadImageObj) {
159 previousResizeTarget_ = imageSize;
160 resizeTarget_ = imageSize;
161 imageLoadingStatus_ = ImageLoadingStatus::LOADING;
162 resizeScale_ = Size(1.0, 1.0);
163 }
164 if (!imageObj_->IsSvg()) {
165 if (sourceInfo_.IsSourceDimensionValid()) {
166 rawImageSize_ = sourceInfo_.GetSourceSize();
167 forceResize_ = true;
168 } else {
169 rawImageSize_ = imageSize;
170 forceResize_ = false;
171 }
172 imageSizeForEvent_ = imageSize;
173 rawImageSizeUpdated_ = true;
174 if (!background_) {
175 currentDstRect_ = dstRect_;
176 } else if (imageUpdateFunc_) {
177 imageUpdateFunc_();
178 }
179 } else {
180 image_ = nullptr;
181 if (useSkiaSvg_) {
182 skiaDom_ = AceType::DynamicCast<SvgSkiaImageObject>(imageObj_)->GetSkiaDom();
183 } else {
184 CacheSvgImageObject();
185 SyncCreateSvgNodes(false);
186 }
187 imageSizeForEvent_ = Measure();
188 UpdateLoadSuccessState();
189 }
190 // If image component size is finally decided, only need to layout itself.
191 bool layoutSizeNotChanged = (previousLayoutSize_ == GetLayoutSize());
192 bool selfOnly = (imageComponentSize_.IsValid() && !imageComponentSize_.IsInfinite() && layoutSizeNotChanged) ||
193 imageObj_->IsSvg();
194 MarkNeedLayout(selfOnly);
195 }
196
ImageObjFailed(const std::string & errorMsg)197 void RosenRenderImage::ImageObjFailed(const std::string& errorMsg)
198 {
199 currentDstRectList_.clear();
200 imageSizeForEvent_ = Size();
201 image_ = nullptr;
202 imageObj_ = nullptr;
203 curSourceInfo_ = sourceInfo_;
204 skiaDom_ = nullptr;
205 svgDom_ = nullptr;
206 proceedPreviousLoading_ = false;
207 imageLoadingStatus_ = ImageLoadingStatus::LOAD_FAIL;
208 retryCnt_ = 0;
209 FireLoadEvent(imageSizeForEvent_, errorMsg);
210 MarkNeedLayout();
211 }
212
ImageDataPaintSuccess(const RefPtr<NG::CanvasImage> & image)213 void RosenRenderImage::ImageDataPaintSuccess(const RefPtr<NG::CanvasImage>& image)
214 {
215 static constexpr double precision = 0.5;
216 int32_t dstWidth = static_cast<int32_t>(previousResizeTarget_.Width() + precision);
217 int32_t dstHeight = static_cast<int32_t>(previousResizeTarget_.Height() + precision);
218 bool isTargetSource = ((dstWidth == image->GetWidth()) && (dstHeight == image->GetHeight()));
219 CHECK_NULL_VOID(imageObj_);
220 if (!isTargetSource && (imageObj_->GetFrameCount() <= 1) && !background_) {
221 return;
222 }
223 UpdateLoadSuccessState();
224 image_ = image;
225 skiaDom_ = nullptr;
226 svgDom_ = nullptr;
227 if (imageDataNotReady_) {
228 imageDataNotReady_ = false;
229 }
230 if (background_) {
231 currentDstRectList_ = rectList_;
232 if (imageUpdateFunc_) {
233 imageUpdateFunc_();
234 }
235 }
236
237 if (GetHidden() && imageObj_->GetFrameCount() > 1) {
238 imageObj_->Pause();
239 }
240 if (imageObj_->GetFrameCount() == 1 && imageObj_->GetSourceInfo().GetSrcType() != SrcType::MEMORY) {
241 imageObj_->ClearData();
242 }
243 CacheImageObject();
244 contentChanged_ = true;
245 }
246
CacheImageObject()247 void RosenRenderImage::CacheImageObject()
248 {
249 auto context = GetContext().Upgrade();
250 if (!context) {
251 return;
252 }
253 auto imageCache = context->GetImageCache();
254 if (imageCache && imageObj_->GetFrameCount() == 1) {
255 imageCache->CacheImgObj(imageObj_->GetSourceInfo().ToString(), imageObj_);
256 }
257 }
258
UpdatePixmap(const RefPtr<PixelMap> & pixmap)259 void RosenRenderImage::UpdatePixmap(const RefPtr<PixelMap>& pixmap)
260 {
261 imageObj_ = MakeRefPtr<PixelMapImageObject>(pixmap);
262 image_ = nullptr;
263 rawImageSize_ = imageObj_->GetImageSize();
264 rawImageSizeUpdated_ = true;
265 MarkNeedLayout();
266 }
267
Update(const RefPtr<Component> & component)268 void RosenRenderImage::Update(const RefPtr<Component>& component)
269 {
270 RenderImage::Update(component);
271 // curImageSrc represents the picture currently shown and imageSrc represents next picture to be shown
272 imageLoadingStatus_ = (sourceInfo_ != curSourceInfo_) ? ImageLoadingStatus::UPDATING : imageLoadingStatus_;
273 UpdateRenderAltImage(component);
274 if (proceedPreviousLoading_ && imageLoadingStatus_ == ImageLoadingStatus::LOAD_SUCCESS) {
275 return;
276 }
277
278 if (sourceInfo_ != curSourceInfo_ && curSourceInfo_.IsValid()) {
279 rawImageSize_ = Size();
280 } else if (curSourceInfo_.IsValid()) {
281 rawImageSize_ = formerRawImageSize_;
282 }
283
284 if (sourceInfo_.IsSvg()) {
285 auto imageObject = QueryCacheSvgImageObject();
286 if (imageObject != nullptr) {
287 imageObj_ = imageObject;
288 SyncCreateSvgNodes(true);
289 return;
290 }
291 }
292
293 FetchImageObject();
294 }
295
GenerateThumbnailLoadTask()296 std::function<void()> RosenRenderImage::GenerateThumbnailLoadTask()
297 {
298 return [sourceInfo = sourceInfo_, pipelineContext = GetContext(), weak = AceType::WeakClaim(this),
299 id = Container::CurrentId()]() {
300 #ifdef OHOS_PLATFORM
301 ContainerScope scope(id);
302 auto context = pipelineContext.Upgrade();
303 if (!context) {
304 return;
305 }
306 auto dataProvider = context->GetDataProviderManager();
307 if (!dataProvider) {
308 return;
309 }
310 void* pixmapMediaUniquePtr = dataProvider->GetDataProviderThumbnailResFromUri(sourceInfo.GetSrc());
311 auto pixmapOhos = PixelMap::CreatePixelMapFromDataAbility(pixmapMediaUniquePtr);
312 auto taskExecutor = context->GetTaskExecutor();
313 if (!taskExecutor) {
314 return;
315 }
316 if (!pixmapOhos) {
317 taskExecutor->PostTask(
318 [weak, sourceInfo] {
319 auto renderImage = weak.Upgrade();
320 if (!renderImage) {
321 return;
322 }
323 renderImage->failedCallback_(sourceInfo,
324 "Fail to get thumbnail data of dataability or datashare, please check the validation of src.");
325 },
326 TaskExecutor::TaskType::UI, "ArkUIImageThumbnailLoadFailed");
327 return;
328 }
329 taskExecutor->PostTask(
330 [weak, pixmapOhos, sourceInfo] {
331 auto renderImage = weak.Upgrade();
332 if (!renderImage) {
333 return;
334 }
335 renderImage->UpdatePixmap(pixmapOhos);
336 },
337 TaskExecutor::TaskType::UI, "ArkUIImageThumbnailLoad");
338 #endif
339 };
340 }
341
FetchImageObject()342 void RosenRenderImage::FetchImageObject()
343 {
344 auto context = GetContext().Upgrade();
345 if (!context) {
346 return;
347 }
348 auto frontend = context->GetFrontend();
349 if (!frontend) {
350 return;
351 }
352 if (!sourceInfo_.IsValid()) {
353 if (context->GetIsDeclarative()) {
354 ImageObjFailed("Invalid image source, input of src may be null, please check.");
355 }
356 return;
357 }
358 rawImageSizeUpdated_ = false;
359 SrcType srcType = sourceInfo_.GetSrcType();
360 switch (srcType) {
361 case SrcType::DATA_ABILITY_DECODED: {
362 BackgroundTaskExecutor::GetInstance().PostTask(GenerateThumbnailLoadTask());
363 break;
364 }
365 case SrcType::PIXMAP: {
366 UpdatePixmap(sourceInfo_.GetPixmap());
367 break;
368 }
369 case SrcType::MEMORY: {
370 UpdateSharedMemoryImage(context);
371 break;
372 }
373 default: {
374 // prevent painting old pixMap while new image is loading
375 if (curSourceInfo_.GetSrcType() == SrcType::PIXMAP) {
376 imageObj_ = nullptr;
377 }
378 bool syncMode = (context->IsBuildingFirstPage() && frontend->GetType() == FrontendType::JS_CARD &&
379 sourceInfo_.GetSrcType() != SrcType::NETWORK) ||
380 syncMode_;
381 ImageProvider::FetchImageObject(sourceInfo_, imageObjSuccessCallback_, uploadSuccessCallback_,
382 failedCallback_, GetContext(), syncMode, useSkiaSvg_, autoResize_, onPostBackgroundTask_);
383 break;
384 }
385 }
386 }
387
UpdateSharedMemoryImage(const RefPtr<PipelineContext> & context)388 void RosenRenderImage::UpdateSharedMemoryImage(const RefPtr<PipelineContext>& context)
389 {
390 auto sharedImageManager = context->GetOrCreateSharedImageManager();
391 if (!sharedImageManager) {
392 return;
393 }
394 auto nameOfSharedImage = ImageLoader::RemovePathHead(sourceInfo_.GetSrc());
395 sharedImageManager->RegisterLoader(nameOfSharedImage, AceType::WeakClaim(this));
396 // This case means that the image to load is a memory image.
397 // Add [this] to [providerMapToReload_] so that it will be notified to start loading image.
398 // When the data is ready, [SharedImageManager] will call [UpdateData] in [AddImageData].
399 sharedImageManager->FindImageInSharedImageMap(nameOfSharedImage, AceType::WeakClaim(this));
400 }
401
PerformLayoutPixmap()402 void RosenRenderImage::PerformLayoutPixmap()
403 {
404 ProcessPixmapForPaint();
405 MarkNeedRender();
406 }
ProcessPixmapForPaint()407 void RosenRenderImage::ProcessPixmapForPaint()
408 {
409 auto pixmap = AceType::DynamicCast<PixelMapImageObject>(imageObj_)->GetPixmap();
410 if (!pixmap) {
411 return;
412 }
413 #ifndef USE_ROSEN_DRAWING
414 // Step1: Create SkPixmap
415 auto imageInfo = MakeSkImageInfoFromPixelMap(pixmap);
416 SkPixmap imagePixmap(imageInfo, reinterpret_cast<const void*>(pixmap->GetPixels()), pixmap->GetRowBytes());
417
418 // Step2: Create SkImage and draw it, using gpu or cpu
419 sk_sp<SkImage> skImage =
420 SkImage::MakeFromRaster(imagePixmap, &PixelMap::ReleaseProc, PixelMap::GetReleaseContext(pixmap));
421 image_ = NG::CanvasImage::Create(&skImage);
422 if (!VerifySkImageDataFromPixmap(pixmap)) {
423 #else
424 // Step1: Create RSBitmap
425 auto rsBitmapFormat = MakeRSBitmapFormatInfoFromPixelMap(pixmap);
426 auto rsBitmap = std::make_shared<RSBitmap>();
427 rsBitmap->Build(pixmap->GetWidth(), pixmap->GetHeight(), rsBitmapFormat);
428 rsBitmap->SetPixels(const_cast<void*>(reinterpret_cast<const void*>(pixmap->GetPixels())));
429
430 // Step2: Create RSImage and draw it, using gpu or cpu
431 auto rsImage = std::make_shared<RSImage>();
432 rsImage->BuildFromBitmap(*rsBitmap);
433 image_ = NG::CanvasImage::Create(&rsImage);
434 if (!VerifyRSImageDataFromPixmap(pixmap)) {
435 #endif
436 imageLoadingStatus_ = ImageLoadingStatus::LOAD_FAIL;
437 FireLoadEvent(Size(), "Image data from PixelMap is invalid, please check PixelMap data.");
438 image_ = nullptr;
439 imageObj_->ClearData();
440 return;
441 }
442 // pixelMap render finished
443 curSourceInfo_ = sourceInfo_;
444 imageLoadingStatus_ = ImageLoadingStatus::LOAD_SUCCESS;
445 FireLoadEvent(rawImageSize_);
446 RemoveChild(renderAltImage_);
447 renderAltImage_ = nullptr;
448 }
449
450 void RosenRenderImage::PerformLayoutSvgImage()
451 {
452 if (svgRenderTree_.root) {
453 ACE_SVG_SCOPED_TRACE("RosenRenderImage::PerformLayoutSvgImage");
454 SvgRadius svgRadius = { topLeftRadius_, topRightRadius_, bottomLeftRadius_, bottomRightRadius_ };
455 svgRenderTree_.containerSize = GetLayoutSize();
456 SvgDom svgDom(context_);
457 svgDom.SetSvgRenderTree(svgRenderTree_);
458 svgDom.UpdateLayout(imageFit_, svgRadius, !directPaint_);
459 }
460 }
461
462 void RosenRenderImage::LayoutImageObject()
463 {
464 if (imageObj_) {
465 imageObj_->PerformLayoutImageObject(AceType::Claim(this));
466 }
467 }
468
469 void RosenRenderImage::SyncCreateSvgNodes(bool isReady)
470 {
471 auto currentSvgDom = AceType::DynamicCast<SvgImageObject>(imageObj_)->GetSvgDom();
472 if (currentSvgDom == nullptr) {
473 return;
474 }
475 svgDom_ = currentSvgDom;
476
477 if (!currentSvgDom->HasAnimate() && !currentSvgDom->HasClipPath()) {
478 directPaint_ = true;
479 }
480 if (directPaint_ == true && isReady) {
481 // svg imageObject from map buffer, use as directly
482 return;
483 }
484 CreateSvgNodes();
485 }
486
487 void RosenRenderImage::CreateSvgNodes()
488 {
489 if (!svgDom_) {
490 return;
491 }
492 ACE_SVG_SCOPED_TRACE("RosenRenderImage::CreateSvgNodes");
493 svgDom_->SetFinishEvent(svgAnimatorFinishEvent_);
494 svgDom_->SetContainerSize(GetLayoutSize());
495 SvgRadius svgRadius = { topLeftRadius_, topRightRadius_, bottomLeftRadius_, bottomRightRadius_ };
496 auto svgRenderTree = svgDom_->CreateRenderTree(imageFit_, svgRadius, !directPaint_);
497 if (svgRenderTree.root == nullptr) {
498 svgDom_ = nullptr;
499 return;
500 }
501 if (!directPaint_) {
502 RebuildSvgRenderTree(svgRenderTree, svgDom_);
503 }
504 }
505
506 void RosenRenderImage::RebuildSvgRenderTree(const SvgRenderTree& svgRenderTree, const RefPtr<SvgDom>& svgDom)
507 {
508 svgRenderTree_ = svgRenderTree;
509 ClearChildren();
510 AddChild(svgRenderTree_.root);
511 MarkNeedRender();
512 }
513
514 void RosenRenderImage::CacheSvgImageObject()
515 {
516 auto context = GetContext().Upgrade();
517 if (!context) {
518 return;
519 }
520 auto imageCache = context->GetImageCache();
521 if (imageCache) {
522 imageCache->CacheImgObj(sourceInfo_.GetKey(), imageObj_);
523 }
524 }
525
526 RefPtr<ImageObject> RosenRenderImage::QueryCacheSvgImageObject()
527 {
528 auto context = GetContext().Upgrade();
529 if (!context) {
530 return nullptr;
531 }
532 auto imageCache = context->GetImageCache();
533 if (imageCache == nullptr) {
534 return nullptr;
535 }
536 return imageCache->GetCacheImgObj(sourceInfo_.GetKey());
537 }
538
539 void RosenRenderImage::Paint(RenderContext& context, const Offset& offset)
540 {
541 if (contentChanged_) {
542 auto rsNode = static_cast<RosenRenderContext*>(&context)->GetRSNode();
543 if (rsNode) {
544 rsNode->MarkContentChanged(true);
545 }
546 contentChanged_ = false;
547 }
548 if (imageObj_ && imageObj_->IsSvg() && !useSkiaSvg_ && !directPaint_) {
549 DrawSVGImageCustom(context, offset);
550 return;
551 }
552 bool sourceDataEmpty = !image_ && !svgDom_ && !skiaDom_;
553 if (renderAltImage_ && sourceDataEmpty) {
554 renderAltImage_->SetDirectPaint(directPaint_);
555 renderAltImage_->RenderWithContext(context, offset);
556 }
557 if (sourceInfo_.GetSrcType() != SrcType::PIXMAP) {
558 UpLoadImageDataForPaint();
559 }
560 auto canvas = static_cast<RosenRenderContext*>(&context)->GetCanvas();
561 if (!canvas) {
562 return;
563 }
564
565 #ifndef USE_ROSEN_DRAWING
566 SkAutoCanvasRestore acr(canvas, true);
567 if (!NearZero(rotate_)) {
568 Offset center =
569 offset + Offset(GetLayoutSize().Width() * SK_ScalarHalf, GetLayoutSize().Height() * SK_ScalarHalf);
570 if (canvas) {
571 canvas->rotate(rotate_, center.GetX(), center.GetY());
572 }
573 }
574 #else
575 RSAutoCanvasRestore acr(*canvas, true);
576 if (!NearZero(rotate_)) {
577 Offset center = offset + Offset(GetLayoutSize().Width() * FLOAT_HALF, GetLayoutSize().Height() * FLOAT_HALF);
578 if (canvas) {
579 canvas->Rotate(rotate_, center.GetX(), center.GetY());
580 }
581 }
582 #endif
583
584 #ifndef USE_ROSEN_DRAWING
585 SkPaint paint;
586 #else
587 RSBrush brush;
588 #endif
589 Rect paintRect =
590 ((imageLoadingStatus_ == ImageLoadingStatus::LOADING) && !resizeCallLoadImage_) ? currentDstRect_ : dstRect_;
591 ApplyBorderRadius(offset, paintRect, canvas);
592 if (imageLoadingStatus_ == ImageLoadingStatus::LOAD_FAIL) {
593 if (renderAltImage_) {
594 return;
595 }
596 auto pipelineContext = GetContext().Upgrade();
597 if (pipelineContext && pipelineContext->GetIsDeclarative()) {
598 // for declarative front end, do not draw anything for developers who use image component, we just inform
599 // them via load fail event and the developers then decide how to react when image loads fail.
600 return;
601 }
602 // to ensure forward compatibility, draw alt color only when it fails to load image
603 #ifndef USE_ROSEN_DRAWING
604 paint.setColor(ALT_COLOR_GREY);
605 #ifdef OHOS_PLATFORM
606 auto recordingCanvas = static_cast<Rosen::RSRecordingCanvas*>(canvas);
607 if (GetBackgroundImageFlag()) {
608 recordingCanvas->drawRect({ offset.GetX(), offset.GetY(), GetLayoutSize().Width() + offset.GetX(),
609 GetLayoutSize().Height() + offset.GetY() },
610 paint);
611 } else {
612 recordingCanvas->DrawAdaptiveRRect(0, paint);
613 }
614 #else
615 canvas->drawRect({ offset.GetX(), offset.GetY(), GetLayoutSize().Width() + offset.GetX(),
616 GetLayoutSize().Height() + offset.GetY() },
617 paint);
618 #endif
619 #else
620 brush.SetColor(ALT_COLOR_GREY);
621 #ifdef OHOS_PLATFORM
622 auto recordingCanvas = static_cast<RSRecordingCanvas*>(canvas);
623 recordingCanvas->AttachBrush(brush);
624 if (GetBackgroundImageFlag()) {
625 recordingCanvas->DrawRect({ offset.GetX(), offset.GetY(), GetLayoutSize().Width() + offset.GetX(),
626 GetLayoutSize().Height() + offset.GetY() });
627 }
628 recordingCanvas->DetachBrush();
629 #else
630 canvas->AttachBrush(brush);
631 canvas->DrawRect({ offset.GetX(), offset.GetY(), GetLayoutSize().Width() + offset.GetX(),
632 GetLayoutSize().Height() + offset.GetY() });
633 canvas->DetachBrush();
634 #endif
635 #endif
636 return;
637 }
638 if (sourceInfo_.IsSvg()) {
639 if (svgDom_) {
640 #ifndef USE_ROSEN_DRAWING
641 canvas->translate(static_cast<float>(offset.GetX()), static_cast<float>(offset.GetY()));
642 #else
643 canvas->Translate(static_cast<float>(offset.GetX()), static_cast<float>(offset.GetY()));
644 #endif
645 svgDom_->PaintDirectly(context, offset, imageFit_, GetLayoutSize());
646 return;
647 }
648 DrawSVGImage(offset, canvas);
649 return;
650 }
651 #ifndef USE_ROSEN_DRAWING
652 ApplyColorFilter(paint);
653 ApplyInterpolation(paint);
654 sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
655 auto skImage = AceType::DynamicCast<NG::SkiaImage>(image_);
656 if (skImage && skImage->GetImage()) {
657 colorSpace = skImage->GetImage()->refColorSpace();
658 }
659
660 paint.setColor(paint.getColor4f(), colorSpace.get());
661
662 #else
663 ApplyColorFilter(brush);
664 ApplyInterpolation(brush);
665 auto colorSpace = RSColorSpace::CreateSRGB();
666 auto rsImage = AceType::DynamicCast<NG::DrawingImage>(image_);
667 if (rsImage && rsImage->GetImage()) {
668 colorSpace = RSRecordingColorSpace::CreateRefImage(*rsImage->GetImage());
669 }
670 brush.SetColor(brush.GetColor4f(), colorSpace);
671 #endif
672 if (GetBackgroundImageFlag()) {
673 PaintBgImage(static_cast<RosenRenderContext*>(&context)->GetRSNode());
674 return;
675 }
676 #ifndef USE_ROSEN_DRAWING
677 CanvasDrawImageRect(paint, offset, canvas, paintRect);
678 #else
679 CanvasDrawImageRect(brush, offset, canvas, paintRect);
680 #endif
681 }
682
683 #ifndef USE_ROSEN_DRAWING
684 void RosenRenderImage::ApplyBorderRadius(const Offset& offset, const Rect& paintRect, SkCanvas* canvas)
685 #else
686 void RosenRenderImage::ApplyBorderRadius(const Offset& offset, const Rect& paintRect, RSCanvas* canvas)
687 #endif
688 {
689 if (GetBackgroundImageFlag()) {
690 return;
691 }
692 SetClipRadius();
693
694 #ifdef OHOS_PLATFORM
695 #ifndef USE_ROSEN_DRAWING
696 auto recordingCanvas = static_cast<Rosen::RSRecordingCanvas*>(canvas);
697 recordingCanvas->ClipAdaptiveRRect(radii_);
698 #else
699 auto recordingCanvas = static_cast<RSRecordingCanvas*>(canvas);
700 recordingCanvas->ClipAdaptiveRoundRect(radii_);
701 #endif
702 #else
703 // There are three situations in which we apply border radius to the whole image component:
704 // 1. when the image source is a SVG;
705 // 2. when image loads fail;
706 // 3. when there is a repeat to do;
707 bool clipLayoutSize = sourceInfo_.IsSvg() || (imageRepeat_ != ImageRepeat::NO_REPEAT) ||
708 (imageLoadingStatus_ == ImageLoadingStatus::LOAD_FAIL);
709 Rect clipRect = clipLayoutSize ? Rect(offset, GetLayoutSize()) : paintRect + offset;
710
711 #ifndef USE_ROSEN_DRAWING
712 SkRRect rrect;
713 rrect.setRectRadii(SkRect::MakeXYWH(clipRect.Left() - imageRenderPosition_.GetX(),
714 clipRect.Top() - imageRenderPosition_.GetY(), clipRect.Width(), clipRect.Height()),
715 radii_);
716 canvas->clipRRect(rrect, true);
717 #else
718 RSRoundRect rrect(
719 RSRect(clipRect.Left() - imageRenderPosition_.GetX(), clipRect.Top() - imageRenderPosition_.GetY(),
720 clipRect.Width() + clipRect.Left() - imageRenderPosition_.GetX(),
721 clipRect.Height() + clipRect.Top() - imageRenderPosition_.GetY()),
722 radii_);
723 canvas->ClipRoundRect(rrect, RSClipOp::INTERSECT, true);
724 #endif
725 #endif
726 }
727
728 #ifndef USE_ROSEN_DRAWING
729 void RosenRenderImage::ApplyColorFilter(SkPaint& paint)
730 #else
731 void RosenRenderImage::ApplyColorFilter(RSBrush& brush)
732 #endif
733 {
734 #ifndef USE_ROSEN_DRAWING
735
736 if (colorfilter_.size() == COLOR_FILTER_MATRIX_SIZE) {
737 float colorfiltermatrix[COLOR_FILTER_MATRIX_SIZE] = { 0 };
738 std::copy(colorfilter_.begin(), colorfilter_.end(), colorfiltermatrix);
739 paint.setColorFilter(SkColorFilters::Matrix(colorfiltermatrix));
740 return;
741 }
742 if (imageRenderMode_ == ImageRenderMode::TEMPLATE) {
743 paint.setColorFilter(SkColorFilters::Matrix(GRAY_COLOR_MATRIX));
744 return;
745 }
746 if (!color_.has_value()) {
747 return;
748 }
749 Color color = color_.value();
750 paint.setColorFilter(SkColorFilters::Blend(
751 SkColorSetARGB(color.GetAlpha(), color.GetRed(), color.GetGreen(), color.GetBlue()), SkBlendMode::kPlus));
752 #else
753 if (colorfilter_.size() == COLOR_FILTER_MATRIX_SIZE) {
754 RSScalar matrixArray[COLOR_FILTER_MATRIX_SIZE] = { 0 };
755 std::copy(colorfilter_.begin(), colorfilter_.end(), matrixArray);
756 RSColorMatrix colorMatrix;
757 colorMatrix.SetArray(matrixArray);
758 auto filter = brush.GetFilter();
759 filter.SetColorFilter(RSRecordingColorFilter::CreateMatrixColorFilter(colorMatrix));
760 brush.SetFilter(filter);
761 return;
762 }
763 if (imageRenderMode_ == ImageRenderMode::TEMPLATE) {
764 auto filter = brush.GetFilter();
765 RSColorMatrix m;
766 m.SetArray(GRAY_COLOR_MATRIX);
767 filter.SetColorFilter(RSRecordingColorFilter::CreateMatrixColorFilter(m));
768 brush.SetFilter(filter);
769 return;
770 }
771 if (!color_.has_value()) {
772 return;
773 }
774 Color color = color_.value();
775 auto filter = brush.GetFilter();
776 filter.SetColorFilter(RSRecordingColorFilter::CreateBlendModeColorFilter(
777 RSColor::ColorQuadSetARGB(color.GetAlpha(), color.GetRed(), color.GetGreen(), color.GetBlue()),
778 RSBlendMode::PLUS));
779 brush.SetFilter(filter);
780 #endif
781 }
782
783 #ifndef USE_ROSEN_DRAWING
784 void RosenRenderImage::ApplyInterpolation(SkPaint& paint)
785 {
786 options_ = SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone);
787 switch (imageInterpolation_) {
788 case ImageInterpolation::LOW:
789 options_ = SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone);
790 break;
791 case ImageInterpolation::MEDIUM:
792 options_ = SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
793 break;
794 case ImageInterpolation::HIGH:
795 options_ = SkSamplingOptions(SkCubicResampler { 1 / 3.0f, 1 / 3.0f });
796 break;
797 case ImageInterpolation::NONE:
798 default:
799 break;
800 }
801 }
802 #else
803 void RosenRenderImage::ApplyInterpolation(RSBrush& brush)
804 {
805 options_ = RSSamplingOptions();
806 switch (imageInterpolation_) {
807 case ImageInterpolation::LOW:
808 options_ = RSSamplingOptions(RSFilterMode::LINEAR, RSMipmapMode::NONE);
809 break;
810 case ImageInterpolation::MEDIUM:
811 options_ = RSSamplingOptions(RSFilterMode::LINEAR, RSMipmapMode::LINEAR);
812 break;
813 case ImageInterpolation::HIGH:
814 options_ = RSSamplingOptions(RSCubicResampler::Mitchell());
815 break;
816 case ImageInterpolation::NONE:
817 default:
818 break;
819 }
820 }
821 #endif
822
823 #ifndef USE_ROSEN_DRAWING
824 void RosenRenderImage::CanvasDrawImageRect(
825 SkPaint& paint, const Offset& offset, SkCanvas* canvas, const Rect& paintRect)
826 #else
827 void RosenRenderImage::CanvasDrawImageRect(
828 RSBrush& brush, const Offset& offset, RSCanvas* canvas, const Rect& paintRect)
829 #endif
830 {
831 if (GetBackgroundImageFlag()) {
832 return;
833 }
834 #ifndef USE_ROSEN_DRAWING
835 auto skImage = AceType::DynamicCast<NG::SkiaImage>(image_);
836 if (!skImage || (!skImage->GetImage() && !skImage->GetCompressData())) {
837 #else
838 auto rsImage = AceType::DynamicCast<NG::DrawingImage>(image_);
839 if (!rsImage || (!rsImage->GetImage() && !rsImage->GetCompressData())) {
840 #endif
841 imageDataNotReady_ = true;
842 return;
843 }
844 int fitNum = static_cast<int>(imageFit_);
845 int repeatNum = static_cast<int>(imageRepeat_);
846 #ifndef USE_ROSEN_DRAWING
847 auto recordingCanvas = static_cast<Rosen::RSRecordingCanvas*>(canvas);
848 if (GetAdaptiveFrameRectFlag()) {
849 recordingCanvas->translate(imageRenderPosition_.GetX() * -1, imageRenderPosition_.GetY() * -1);
850 Rosen::RsImageInfo rsImageInfo(
851 fitNum, repeatNum, radii_, scale_, 0, skImage->GetCompressWidth(), skImage->GetCompressHeight());
852
853 recordingCanvas->DrawImageWithParm(
854 skImage->GetImage(), skImage->GetCompressData(), rsImageInfo, options_, paint);
855 skImage->SetCompressData(nullptr, 0, 0);
856 return;
857 #else
858 auto recordingCanvas = static_cast<Rosen::ExtendRecordingCanvas*>(canvas);
859 if (GetAdaptiveFrameRectFlag()) {
860 recordingCanvas->Translate(imageRenderPosition_.GetX() * -1, imageRenderPosition_.GetY() * -1);
861 Rosen::Drawing::AdaptiveImageInfo rsImageInfo = { fitNum, repeatNum,
862 { radii_[0], radii_[1], radii_[2], radii_[3] }, scale_, 0, rsImage->GetCompressWidth(),
863 rsImage->GetCompressHeight() };
864 recordingCanvas->AttachBrush(brush);
865 recordingCanvas->DrawImageWithParm(rsImage->GetImage(), rsImage->GetCompressData(), rsImageInfo, options_);
866 recordingCanvas->DetachBrush();
867 rsImage->SetCompressData(nullptr, 0, 0);
868 return;
869 #endif
870 }
871 bool isLoading =
872 ((imageLoadingStatus_ == ImageLoadingStatus::LOADING) || (imageLoadingStatus_ == ImageLoadingStatus::UPDATING));
873 Rect scaledSrcRect = isLoading ? currentSrcRect_ : srcRect_;
874
875 if (sourceInfo_.IsValid() && imageObj_ && (imageObj_->GetFrameCount() == 1)) {
876 #ifndef USE_ROSEN_DRAWING
877 Size sourceSize = (skImage ? Size(skImage->GetWidth(), skImage->GetHeight()) : Size());
878 #else
879 Size sourceSize = (rsImage ? Size(rsImage->GetWidth(), rsImage->GetHeight()) : Size());
880 #endif
881 // calculate srcRect that matches the real image source size
882 // note that gif doesn't do resize, so gif does not need to recalculate
883 scaledSrcRect = RecalculateSrcRect(sourceSize);
884 scaledSrcRect.ApplyScaleAndRound(currentResizeScale_);
885 }
886
887 Rect realDstRect = paintRect + offset;
888
889 if (imageRepeat_ != ImageRepeat::NO_REPEAT) {
890 #ifndef USE_ROSEN_DRAWING
891 DrawImageOnCanvas(scaledSrcRect, realDstRect, paint, canvas);
892 #else
893 DrawImageOnCanvas(scaledSrcRect, realDstRect, brush, canvas);
894 #endif
895 return;
896 }
897 #ifndef USE_ROSEN_DRAWING
898 auto skSrcRect =
899 SkRect::MakeXYWH(scaledSrcRect.Left(), scaledSrcRect.Top(), scaledSrcRect.Width(), scaledSrcRect.Height());
900 auto skDstRect = SkRect::MakeXYWH(realDstRect.Left() - imageRenderPosition_.GetX(),
901 realDstRect.Top() - imageRenderPosition_.GetY(), realDstRect.Width(), realDstRect.Height());
902
903 canvas->drawImageRect(
904 skImage->GetImage(), skSrcRect, skDstRect, options_, &paint, SkCanvas::kFast_SrcRectConstraint);
905 #else
906 auto srcRect = RSRect(scaledSrcRect.Left(), scaledSrcRect.Top(), scaledSrcRect.Right(), scaledSrcRect.Bottom());
907 auto dstRect =
908 RSRect(realDstRect.Left() - imageRenderPosition_.GetX(), realDstRect.Top() - imageRenderPosition_.GetY(),
909 realDstRect.Right() - imageRenderPosition_.GetX(), realDstRect.Bottom() - imageRenderPosition_.GetY());
910 canvas->AttachBrush(brush);
911 canvas->DrawImageRect(*rsImage->GetImage(), srcRect, dstRect, options_);
912 canvas->DetachBrush();
913 #endif
914 }
915
916 #ifndef USE_ROSEN_DRAWING
917 void RosenRenderImage::DrawImageOnCanvas(
918 const Rect& srcRect, const Rect& dstRect, const SkPaint& paint, SkCanvas* canvas) const
919 {
920 #ifdef OHOS_PLATFORM
921 auto recordingCanvas = static_cast<Rosen::RSRecordingCanvas*>(canvas);
922
923 auto skSrcRect =
924 SkRect::MakeXYWH(Round(srcRect.Left()), Round(srcRect.Top()), Round(srcRect.Width()), Round(srcRect.Height()));
925 // only transform one time, set skDstRect.top and skDstRect.left to 0.
926 auto skDstRect = SkRect::MakeXYWH(0, 0, dstRect.Width(), dstRect.Height());
927
928 // initialize a transform matrix
929 SkScalar scaleX = skDstRect.width() / skSrcRect.width();
930 SkScalar scaleY = skDstRect.height() / skSrcRect.height();
931 SkScalar transX = dstRect.Left() - imageRenderPosition_.GetX();
932 SkScalar transY = dstRect.Top() - imageRenderPosition_.GetY();
933 if (matchTextDirection_ && GetTextDirection() == TextDirection::RTL) {
934 // flip the image algin x direction.
935 scaleX = -1 * scaleX;
936 transX = skDstRect.left() + skDstRect.width();
937 }
938 SkScalar skewX = 0;
939 SkScalar skewY = 0;
940 SkScalar pers0 = 0;
941 SkScalar pers1 = 0;
942 SkScalar pers2 = 1;
943 auto sampleMatrix = SkMatrix::MakeAll(scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2);
944
945 recordingCanvas->save();
946 recordingCanvas->concat(sampleMatrix);
947 auto skImage = AceType::DynamicCast<NG::SkiaImage>(image_);
948 if (skImage && skImage->GetImage()) {
949 recordingCanvas->drawImageRect(
950 skImage->GetImage(), skSrcRect, skDstRect, options_, &paint, SkCanvas::kFast_SrcRectConstraint);
951 }
952 recordingCanvas->restore();
953 #endif
954 }
955 #else
956 void RosenRenderImage::DrawImageOnCanvas(
957 const Rect& srcRect, const Rect& dstRect, const RSBrush& brush, RSCanvas* canvas) const
958 {
959 #ifdef OHOS_PLATFORM
960 auto recordingCanvas = static_cast<RSRecordingCanvas*>(canvas);
961 auto drSrcRect =
962 RSRect(Round(srcRect.Left()), Round(srcRect.Top()), Round(srcRect.Right()), Round(srcRect.Bottom()));
963 // only transform one time, set skDstRect.top and skDstRect.left to 0.
964 auto drDstRect = RSRect(0, 0, dstRect.Width(), dstRect.Height());
965
966 // initialize a transform matrix
967 RSScalar scaleX = drDstRect.GetWidth() / drSrcRect.GetWidth();
968 RSScalar scaleY = drDstRect.GetHeight() / drSrcRect.GetHeight();
969 RSScalar transX = dstRect.Left() - imageRenderPosition_.GetX();
970 RSScalar transY = dstRect.Top() - imageRenderPosition_.GetY();
971 if (matchTextDirection_ && GetTextDirection() == TextDirection::RTL) {
972 // flip the image algin x direction.
973 scaleX = -1 * scaleX;
974 transX = drDstRect.GetLeft() + drDstRect.GetWidth();
975 }
976 RSScalar skewX = 0;
977 RSScalar skewY = 0;
978 RSScalar pers0 = 0;
979 RSScalar pers1 = 0;
980 RSScalar pers2 = 1;
981 RSMatrix sampleMatrix;
982 sampleMatrix.SetMatrix(scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2);
983
984 recordingCanvas->Save();
985 recordingCanvas->ConcatMatrix(sampleMatrix);
986
987 auto rsImage = AceType::DynamicCast<NG::DrawingImage>(image_);
988 if (rsImage && rsImage->GetImage()) {
989 recordingCanvas->AttachBrush(brush);
990 recordingCanvas->DrawImageRect(
991 *rsImage->GetImage(), drSrcRect, drDstRect, options_, RSSrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
992 recordingCanvas->DetachBrush();
993 }
994 recordingCanvas->Restore();
995 #endif
996 }
997 #endif
998
999 #ifndef USE_ROSEN_DRAWING
1000 bool RosenRenderImage::VerifySkImageDataFromPixmap(const RefPtr<PixelMap>& pixmap) const
1001 {
1002 auto skImage = AceType::DynamicCast<NG::SkiaImage>(image_);
1003 if (!skImage || !skImage->GetImage()) {
1004 return false;
1005 }
1006 if ((skImage->GetWidth() <= 0 || skImage->GetHeight() <= 0)) {
1007 return false;
1008 }
1009 return true;
1010 }
1011 #else
1012 bool RosenRenderImage::VerifyRSImageDataFromPixmap(const RefPtr<PixelMap>& pixmap) const
1013 {
1014 auto rsImage = AceType::DynamicCast<NG::DrawingImage>(image_);
1015 if (!rsImage || !rsImage->GetImage()) {
1016 return false;
1017 }
1018 if ((rsImage->GetWidth() <= 0 || rsImage->GetHeight() <= 0)) {
1019 return false;
1020 }
1021 return true;
1022 }
1023 #endif
1024
1025 Rect RosenRenderImage::RecalculateSrcRect(const Size& realImageSize)
1026 {
1027 if (!currentResizeScale_.IsValid() || scale_ <= 0.0) {
1028 return Rect();
1029 }
1030 auto realSrcSize = Size(
1031 realImageSize.Width() / currentResizeScale_.Width(), realImageSize.Height() / currentResizeScale_.Height());
1032 Rect realSrcRect(Offset(), realSrcSize * (1.0 / scale_));
1033 Rect realDstRect(Offset(), GetLayoutSize());
1034 ApplyImageFit(realSrcRect, realDstRect);
1035 realSrcRect.ApplyScale(scale_);
1036 return realSrcRect;
1037 }
1038
1039 void RosenRenderImage::PaintBgImage(const std::shared_ptr<RSNode>& rsNode)
1040 {
1041 if (!GetBackgroundImageFlag()) {
1042 return;
1043 }
1044 #ifndef USE_ROSEN_DRAWING
1045 auto skImage = AceType::DynamicCast<NG::SkiaImage>(image_);
1046 if (currentDstRectList_.empty() || !skImage || !skImage->GetImage()) {
1047 #else
1048 auto rsImage = AceType::DynamicCast<NG::DrawingImage>(image_);
1049 if (currentDstRectList_.empty() || !rsImage || !rsImage->GetImage()) {
1050 #endif
1051 return;
1052 }
1053
1054 if (!rsNode) {
1055 return;
1056 }
1057 auto rosenImage = std::make_shared<Rosen::RSImage>();
1058 #ifndef USE_ROSEN_DRAWING
1059 rosenImage->SetImage(skImage->GetImage());
1060 #else
1061 rosenImage->SetImage(rsImage->GetImage());
1062 #endif
1063 rosenImage->SetImageRepeat(static_cast<int>(imageRepeat_));
1064 rsNode->SetBgImageWidth(imageRenderSize_.Width());
1065 rsNode->SetBgImageHeight(imageRenderSize_.Height());
1066 rsNode->SetBgImagePositionX(imageRenderPosition_.GetX());
1067 rsNode->SetBgImagePositionY(imageRenderPosition_.GetY());
1068 rsNode->SetBgImage(rosenImage);
1069 }
1070
1071 bool RosenRenderImage::NeedUploadImageObjToGpu()
1072 {
1073 bool sourceChange = sourceInfo_ != curSourceInfo_;
1074 bool newSourceCallLoadImage = (sourceChange && rawImageSize_.IsValid() && srcRect_.IsValid() &&
1075 (rawImageSizeUpdated_ && imageLoadingStatus_ != ImageLoadingStatus::LOADING) &&
1076 imageLoadingStatus_ != ImageLoadingStatus::LOAD_FAIL);
1077 if (imageLoadingStatus_ != ImageLoadingStatus::LOADING) {
1078 resizeCallLoadImage_ =
1079 !sourceChange && NeedResize() && (imageLoadingStatus_ == ImageLoadingStatus::LOAD_SUCCESS);
1080 }
1081 return (newSourceCallLoadImage && (background_ || resizeTarget_.IsValid())) ||
1082 (resizeCallLoadImage_ && autoResize_);
1083 }
1084
1085 void RosenRenderImage::UpLoadImageDataForPaint()
1086 {
1087 if (NeedUploadImageObjToGpu()) {
1088 imageLoadingStatus_ = ImageLoadingStatus::LOADING;
1089 if (imageObj_) {
1090 previousResizeTarget_ = resizeTarget_;
1091 RosenRenderImage::UploadImageObjToGpuForRender(imageObj_, GetContext(), uploadSuccessCallback_,
1092 failedCallback_, resizeTarget_, forceResize_, syncMode_);
1093 }
1094 }
1095 }
1096
1097 void RosenRenderImage::UploadImageObjToGpuForRender(const RefPtr<ImageObject>& imageObj,
1098 const WeakPtr<PipelineContext> context, UploadSuccessCallback uploadSuccessCallback, FailedCallback failedCallback,
1099 Size resizeTarget, bool forceResize, bool syncMode)
1100 {
1101 if (!imageObj) {
1102 return;
1103 }
1104 imageObj->UploadToGpuForRender(context, uploadSuccessCallback, failedCallback, resizeTarget, forceResize, syncMode);
1105 }
1106
1107 void RosenRenderImage::UpdateData(const std::string& uri, const std::vector<uint8_t>& memData)
1108 {
1109 if (uri != sourceInfo_.GetSrc()) {
1110 return;
1111 }
1112 #ifndef USE_ROSEN_DRAWING
1113 auto skData = SkData::MakeWithCopy(memData.data(), memData.size());
1114 if (!skData) {
1115 #else
1116 auto rsData = std::make_shared<RSData>();
1117 rsData->BuildWithCopy(memData.data(), memData.size());
1118 if (!rsData) {
1119 #endif
1120 return;
1121 }
1122 if (sourceInfo_.IsSvg()) {
1123 #ifndef USE_ROSEN_DRAWING
1124 PaintSVGImage(skData, true);
1125 #else
1126 PaintSVGImage(rsData, true);
1127 #endif
1128 return;
1129 }
1130 #ifndef USE_ROSEN_DRAWING
1131 auto codec = SkCodec::MakeFromData(skData);
1132 #else
1133 auto skData = SkData::MakeWithoutCopy(rsData->GetData(), rsData->GetSize());
1134 auto codec = SkCodec::MakeFromData(skData);
1135 #endif
1136 if (!codec) {
1137 return;
1138 }
1139
1140 auto context = GetContext().Upgrade();
1141 if (!context) {
1142 return;
1143 }
1144 #ifndef USE_ROSEN_DRAWING
1145 auto ImageObj = ImageObject::BuildImageObject(sourceInfo_, context, skData, useSkiaSvg_);
1146 #else
1147 auto ImageObj = ImageObject::BuildImageObject(sourceInfo_, context, rsData, useSkiaSvg_);
1148 #endif
1149 if (!ImageObj) {
1150 return;
1151 }
1152 ImageObjReady(ImageObj);
1153 }
1154
1155 void RosenRenderImage::SetClipRadius()
1156 {
1157 #ifndef USE_ROSEN_DRAWING
1158 SetSkRadii(topLeftRadius_, radii_[SkRRect::kUpperLeft_Corner]);
1159 SetSkRadii(topRightRadius_, radii_[SkRRect::kUpperRight_Corner]);
1160 SetSkRadii(bottomLeftRadius_, radii_[SkRRect::kLowerLeft_Corner]);
1161 SetSkRadii(bottomRightRadius_, radii_[SkRRect::kLowerRight_Corner]);
1162 #else
1163 SetRadii(topLeftRadius_, radii_[RSRoundRect::CornerPos::TOP_LEFT_POS]);
1164 SetRadii(topRightRadius_, radii_[RSRoundRect::CornerPos::TOP_RIGHT_POS]);
1165 SetRadii(bottomLeftRadius_, radii_[RSRoundRect::CornerPos::BOTTOM_LEFT_POS]);
1166 SetRadii(bottomRightRadius_, radii_[RSRoundRect::CornerPos::BOTTOM_RIGHT_POS]);
1167 #endif
1168 }
1169
1170 #ifndef USE_ROSEN_DRAWING
1171 void RosenRenderImage::SetSkRadii(const Radius& radius, SkVector& radii)
1172 #else
1173 void RosenRenderImage::SetRadii(const Radius& radius, RSPoint& radii)
1174 #endif
1175 {
1176 auto context = context_.Upgrade();
1177 if (!context) {
1178 return;
1179 }
1180 double dipScale = context->GetDipScale();
1181 #ifndef USE_ROSEN_DRAWING
1182 radii.set(SkDoubleToScalar(std::max(radius.GetX().ConvertToPx(dipScale), 0.0)),
1183 SkDoubleToScalar(std::max(radius.GetY().ConvertToPx(dipScale), 0.0)));
1184 #else
1185 radii = { static_cast<RSScalar>(std::max(radius.GetX().ConvertToPx(dipScale), 0.0)),
1186 static_cast<RSScalar>(std::max(radius.GetY().ConvertToPx(dipScale), 0.0)) };
1187 #endif
1188 }
1189
1190 Size RosenRenderImage::MeasureForPixmap()
1191 {
1192 return rawImageSize_;
1193 }
1194
1195 Size RosenRenderImage::MeasureForSvgImage()
1196 {
1197 return imageComponentSize_;
1198 }
1199
1200 Size RosenRenderImage::MeasureForNormalImage()
1201 {
1202 switch (imageLoadingStatus_) {
1203 case ImageLoadingStatus::LOAD_SUCCESS:
1204 case ImageLoadingStatus::LOADING:
1205 case ImageLoadingStatus::UNLOADED:
1206 case ImageLoadingStatus::LOAD_FAIL:
1207 return rawImageSize_;
1208 case ImageLoadingStatus::UPDATING:
1209 if (rawImageSizeUpdated_) {
1210 return rawImageSize_;
1211 }
1212 return formerRawImageSize_;
1213 default:
1214 return Size();
1215 }
1216 }
1217
1218 Size RosenRenderImage::Measure()
1219 {
1220 if (imageObj_) {
1221 return imageObj_->MeasureForImage(AceType::Claim(this));
1222 }
1223 return Size();
1224 }
1225
1226 void RosenRenderImage::OnHiddenChanged(bool hidden)
1227 {
1228 if (hidden) {
1229 if (imageObj_ && imageObj_->GetFrameCount() > 1) {
1230 imageObj_->Pause();
1231 } else if (sourceInfo_.GetSrcType() != SrcType::MEMORY) {
1232 CancelBackgroundTasks();
1233 }
1234 } else {
1235 if (imageObj_ && imageObj_->GetFrameCount() > 1 && GetVisible()) {
1236 imageObj_->Resume();
1237 } else if (backgroundTaskCanceled_) {
1238 backgroundTaskCanceled_ = false;
1239 if (sourceInfo_.GetSrcType() == SrcType::MEMORY) {
1240 }
1241 imageLoadingStatus_ = ImageLoadingStatus::UNLOADED;
1242 FetchImageObject();
1243 }
1244 }
1245 }
1246
1247 void RosenRenderImage::CancelBackgroundTasks()
1248 {
1249 if (fetchImageObjTask_) {
1250 backgroundTaskCanceled_ = fetchImageObjTask_.Cancel(false);
1251 }
1252 if (imageObj_) {
1253 backgroundTaskCanceled_ = imageObj_->CancelBackgroundTasks();
1254 }
1255 }
1256
1257 #ifndef USE_ROSEN_DRAWING
1258 void RosenRenderImage::PaintSVGImage(const sk_sp<SkData>& skData, bool onlyLayoutSelf)
1259 #else
1260 void RosenRenderImage::PaintSVGImage(const std::shared_ptr<RSData>& drawingData, bool onlyLayoutSelf)
1261 #endif
1262 {
1263 imageLoadingStatus_ = ImageLoadingStatus::LOADING;
1264 auto successCallback = [svgImageWeak = AceType::WeakClaim(this), onlyLayoutSelf](const sk_sp<SkSVGDOM>& svgDom) {
1265 auto svgImage = svgImageWeak.Upgrade();
1266 if (!svgImage) {
1267 return;
1268 }
1269 svgImage->skiaDom_ = svgDom;
1270 svgImage->image_ = nullptr;
1271 svgImage->imageSizeForEvent_ = svgImage->Measure();
1272 svgImage->UpdateLoadSuccessState();
1273 svgImage->MarkNeedLayout(onlyLayoutSelf);
1274 };
1275 auto failedCallback = [svgImageWeak = AceType::WeakClaim(this)]() {
1276 auto svgImage = svgImageWeak.Upgrade();
1277 if (svgImage) {
1278 // if Upgrade fail, just callback with nullptr
1279 svgImage->ImageObjFailed("SVG data may be broken, please check the SVG file.");
1280 }
1281 };
1282 #ifndef USE_ROSEN_DRAWING
1283 SkColorEx skColor;
1284 auto fillColor = sourceInfo_.GetFillColor();
1285 if (fillColor.has_value()) {
1286 skColor.color = fillColor.value().GetValue();
1287 skColor.valid = 1;
1288 }
1289 ImageProvider::GetSVGImageDOMAsyncFromData(
1290 skData, successCallback, failedCallback, GetContext(), skColor.value, onPostBackgroundTask_);
1291 #else
1292 DrawingColorEx drawingColor;
1293 auto fillColor = sourceInfo_.GetFillColor();
1294 if (fillColor.has_value()) {
1295 drawingColor.color = fillColor.value().GetValue();
1296 drawingColor.valid = 1;
1297 }
1298 ImageProvider::GetSVGImageDOMAsyncFromData(
1299 drawingData, successCallback, failedCallback, GetContext(), drawingColor.value, onPostBackgroundTask_);
1300 #endif
1301 MarkNeedLayout();
1302 }
1303
1304 #ifndef USE_ROSEN_DRAWING
1305 void RosenRenderImage::DrawSVGImage(const Offset& offset, SkCanvas* canvas)
1306 #else
1307 void RosenRenderImage::DrawSVGImage(const Offset& offset, RSCanvas* canvas)
1308 #endif
1309 {
1310 if (!skiaDom_) {
1311 return;
1312 }
1313 Size layoutSize = GetLayoutSize();
1314 Size imageSize(skiaDom_->containerSize().width(), skiaDom_->containerSize().height());
1315 if (layoutSize.IsInfinite() || !layoutSize.IsValid()) {
1316 if (imageSize.IsInfinite() || !imageSize.IsValid()) {
1317 return;
1318 }
1319 // when layout size is invalid, use svg's own size
1320 layoutSize = imageSize;
1321 }
1322
1323 #ifndef USE_ROSEN_DRAWING
1324 canvas->translate(static_cast<float>(offset.GetX()), static_cast<float>(offset.GetY()));
1325
1326 auto width = static_cast<float>(layoutSize.Width());
1327 auto height = static_cast<float>(layoutSize.Height());
1328 if (matchTextDirection_ && GetTextDirection() == TextDirection::RTL) {
1329 canvas->translate(width, 0);
1330 canvas->scale(-1, 1);
1331 }
1332 canvas->clipRect({ 0, 0, width, height }, SkClipOp::kIntersect, true);
1333 if (imageSize.IsValid() && !imageSize.IsInfinite()) {
1334 // scale svg to layout size
1335 float scale = std::min(width / imageSize.Width(), height / imageSize.Height());
1336 canvas->scale(scale, scale);
1337 } else {
1338 skiaDom_->setContainerSize({ width, height });
1339 }
1340 skiaDom_->render(canvas);
1341 #else
1342 canvas->Translate(static_cast<float>(offset.GetX()), static_cast<float>(offset.GetY()));
1343
1344 auto width = static_cast<float>(layoutSize.Width());
1345 auto height = static_cast<float>(layoutSize.Height());
1346 if (matchTextDirection_ && GetTextDirection() == TextDirection::RTL) {
1347 canvas->Translate(width, 0);
1348 canvas->Scale(-1, 1);
1349 }
1350 canvas->ClipRect(RSRect(0, 0, width, height), RSClipOp::INTERSECT, true);
1351 if (imageSize.IsValid() && !imageSize.IsInfinite()) {
1352 // scale svg to layout size
1353 float scale = std::min(width / imageSize.Width(), height / imageSize.Height());
1354 canvas->Scale(scale, scale);
1355 } else {
1356 skiaDom_->setContainerSize({ width, height });
1357 }
1358 canvas->DrawSVGDOM(skiaDom_);
1359 #endif
1360 }
1361
1362 void RosenRenderImage::DrawSVGImageCustom(RenderContext& context, const Offset& offset)
1363 {
1364 if (svgRenderTree_.root) {
1365 PaintChild(svgRenderTree_.root, context, offset);
1366 }
1367 }
1368
1369 void RosenRenderImage::UpdateLoadSuccessState()
1370 {
1371 imageLoadingStatus_ = ImageLoadingStatus::LOAD_SUCCESS;
1372 if (!imageObj_) {
1373 return;
1374 }
1375 auto currentFrameCount = imageObj_->GetFrameCount();
1376 if ((!sourceInfo_.IsSvg() && currentFrameCount == 1) || (currentFrameCount > 1 && curSourceInfo_ != sourceInfo_)) {
1377 FireLoadEvent(imageSizeForEvent_);
1378 }
1379 // alt_image has empty imageAlt_, then mark the parent needs render
1380 if ((currentFrameCount > 1 && curSourceInfo_ != sourceInfo_) || imageAlt_.empty()) {
1381 auto parent = GetParent().Upgrade();
1382 if (parent) {
1383 parent->MarkNeedRender();
1384 }
1385 }
1386 if (currentFrameCount != frameCount_) {
1387 frameCount_ = currentFrameCount;
1388 }
1389
1390 currentSrcRect_ = srcRect_;
1391 curSourceInfo_ = sourceInfo_;
1392 formerRawImageSize_ = rawImageSize_;
1393 forceResize_ = false;
1394 retryCnt_ = 0;
1395 currentResizeScale_ = resizeScale_;
1396 if (renderAltImage_) {
1397 RemoveChild(renderAltImage_);
1398 renderAltImage_ = nullptr;
1399 MarkNeedLayout();
1400 return;
1401 }
1402 proceedPreviousLoading_ = false;
1403 rawImageSizeUpdated_ = false;
1404 MarkNeedRender();
1405 }
1406
1407 void RosenRenderImage::UpdateRenderAltImage(const RefPtr<Component>& component)
1408 {
1409 const RefPtr<ImageComponent> image = AceType::DynamicCast<ImageComponent>(component);
1410 if (!image) {
1411 return;
1412 }
1413 bool imageAltValid = !imageAlt_.empty() && (imageAlt_ != IMAGE_ALT_BLANK);
1414 if (!imageAltValid || imageLoadingStatus_ == ImageLoadingStatus::LOAD_SUCCESS) {
1415 return;
1416 }
1417 // note that alt image component must be a copy
1418 RefPtr<ImageComponent> altImageComponent = ImageComponent::MakeFromOtherWithoutSourceAndEvent(image);
1419 altImageComponent->SetSrc(imageAlt_);
1420 altImageComponent->SetAlt("");
1421 if (renderAltImage_) {
1422 renderAltImage_->Update(altImageComponent);
1423 return;
1424 }
1425 renderAltImage_ = AceType::DynamicCast<RenderImage>(altImageComponent->CreateRenderNode());
1426 renderAltImage_->Attach(GetContext());
1427 renderAltImage_->Update(altImageComponent);
1428 AddChild(renderAltImage_);
1429 }
1430
1431 bool RosenRenderImage::MaybeRelease()
1432 {
1433 auto context = GetContext().Upgrade();
1434 if (context && context->GetRenderFactory() && context->GetRenderFactory()->GetRenderImageFactory()->Recycle(this)) {
1435 ClearRenderObject();
1436 return false;
1437 }
1438 return true;
1439 }
1440
1441 void RosenRenderImage::ClearRenderObject()
1442 {
1443 RenderImage::ClearRenderObject();
1444 CancelBackgroundTasks();
1445 curSourceInfo_.Reset();
1446 image_ = nullptr;
1447 formerRawImageSize_ = { 0.0, 0.0 };
1448 imageObj_ = nullptr;
1449 skiaDom_ = nullptr;
1450 svgDom_ = nullptr;
1451 svgRenderTree_.ClearRenderObject();
1452 }
1453
1454 bool RosenRenderImage::IsSourceWideGamut() const
1455 {
1456 #ifndef USE_ROSEN_DRAWING
1457 auto skImage = AceType::DynamicCast<NG::SkiaImage>(image_);
1458 if (sourceInfo_.IsSvg() || !skImage || !skImage->GetImage()) {
1459 return false;
1460 }
1461 return ImageProvider::IsWideGamut(skImage->GetImage()->refColorSpace());
1462 #else
1463 auto rsImage = AceType::DynamicCast<NG::DrawingImage>(image_);
1464 if (sourceInfo_.IsSvg() || !rsImage || !rsImage->GetImage()) {
1465 return false;
1466 }
1467 return ImageProvider::IsWideGamut(RSColorSpace::CreateRefImage(*rsImage->GetImage()));
1468 #endif
1469 }
1470
1471 bool RosenRenderImage::RetryLoading()
1472 {
1473 if (!sourceInfo_.IsValid()) {
1474 return false;
1475 }
1476 if (retryCnt_++ > 5) { // retry loading 5 times at most
1477 return false;
1478 }
1479
1480 if (rawImageSizeUpdated_ && imageObj_) { // case when image size is ready, only have to do loading again
1481 imageObj_->UploadToGpuForRender(
1482 GetContext(), uploadSuccessCallback_, failedCallback_, resizeTarget_, forceResize_);
1483 return true;
1484 }
1485 // case when the fail event is triggered by GetImageSize, do GetImageSize again
1486 auto context = GetContext().Upgrade();
1487 if (!context) {
1488 return false;
1489 }
1490 auto frontend = context->GetFrontend();
1491 if (!frontend) {
1492 return false;
1493 }
1494 bool syncMode = context->IsBuildingFirstPage() && frontend->GetType() == FrontendType::JS_CARD &&
1495 sourceInfo_.GetSrcType() != SrcType::NETWORK;
1496 ImageProvider::FetchImageObject(sourceInfo_, imageObjSuccessCallback_, uploadSuccessCallback_, failedCallback_,
1497 GetContext(), syncMode, useSkiaSvg_, autoResize_, onPostBackgroundTask_);
1498 return true;
1499 }
1500
1501 #ifndef USE_ROSEN_DRAWING
1502 SkImageInfo RosenRenderImage::MakeSkImageInfoFromPixelMap(const RefPtr<PixelMap>& pixmap)
1503 {
1504 SkColorType ct = PixelFormatToSkColorType(pixmap);
1505 SkAlphaType at = AlphaTypeToSkAlphaType(pixmap);
1506 sk_sp<SkColorSpace> cs = ColorSpaceToSkColorSpace(pixmap);
1507 return SkImageInfo::Make(pixmap->GetWidth(), pixmap->GetHeight(), ct, at, cs);
1508 }
1509 #else
1510 RSBitmapFormat RosenRenderImage::MakeRSBitmapFormatInfoFromPixelMap(const RefPtr<PixelMap>& pixmap)
1511 {
1512 return { PixelFormatToRSColorType(pixmap), AlphaTypeToRSAlphaType(pixmap) };
1513 }
1514 #endif
1515
1516 #ifndef USE_ROSEN_DRAWING
1517 sk_sp<SkColorSpace> RosenRenderImage::ColorSpaceToSkColorSpace(const RefPtr<PixelMap>& pixmap)
1518 {
1519 return SkColorSpace::MakeSRGB(); // Media::PixelMap has not support wide gamut yet.
1520 }
1521 #endif
1522
1523 #ifndef USE_ROSEN_DRAWING
1524 SkAlphaType RosenRenderImage::AlphaTypeToSkAlphaType(const RefPtr<PixelMap>& pixmap)
1525 {
1526 switch (pixmap->GetAlphaType()) {
1527 case AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
1528 return SkAlphaType::kUnknown_SkAlphaType;
1529 case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
1530 return SkAlphaType::kOpaque_SkAlphaType;
1531 case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
1532 return SkAlphaType::kPremul_SkAlphaType;
1533 case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
1534 return SkAlphaType::kUnpremul_SkAlphaType;
1535 default:
1536 return SkAlphaType::kUnknown_SkAlphaType;
1537 }
1538 }
1539 #else
1540 Rosen::Drawing::AlphaType RosenRenderImage::AlphaTypeToRSAlphaType(const RefPtr<PixelMap>& pixmap)
1541 {
1542 switch (pixmap->GetAlphaType()) {
1543 case AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
1544 return Rosen::Drawing::AlphaType::ALPHATYPE_UNKNOWN;
1545 case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
1546 return Rosen::Drawing::AlphaType::ALPHATYPE_OPAQUE;
1547 case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
1548 return Rosen::Drawing::AlphaType::ALPHATYPE_PREMUL;
1549 case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
1550 return Rosen::Drawing::AlphaType::ALPHATYPE_UNPREMUL;
1551 default:
1552 return Rosen::Drawing::AlphaType::ALPHATYPE_UNKNOWN;
1553 }
1554 }
1555 #endif
1556
1557 #ifndef USE_ROSEN_DRAWING
1558 SkColorType RosenRenderImage::PixelFormatToSkColorType(const RefPtr<PixelMap>& pixmap)
1559 {
1560 switch (pixmap->GetPixelFormat()) {
1561 case PixelFormat::RGB_565:
1562 return SkColorType::kRGB_565_SkColorType;
1563 case PixelFormat::RGBA_8888:
1564 return SkColorType::kRGBA_8888_SkColorType;
1565 case PixelFormat::BGRA_8888:
1566 return SkColorType::kBGRA_8888_SkColorType;
1567 case PixelFormat::ALPHA_8:
1568 return SkColorType::kAlpha_8_SkColorType;
1569 case PixelFormat::RGBA_F16:
1570 return SkColorType::kRGBA_F16_SkColorType;
1571 case PixelFormat::UNKNOWN:
1572 case PixelFormat::ARGB_8888:
1573 case PixelFormat::RGB_888:
1574 case PixelFormat::NV21:
1575 case PixelFormat::NV12:
1576 case PixelFormat::CMYK:
1577 default:
1578 return SkColorType::kUnknown_SkColorType;
1579 }
1580 }
1581 #else
1582 Rosen::Drawing::ColorType RosenRenderImage::PixelFormatToRSColorType(const RefPtr<PixelMap>& pixmap)
1583 {
1584 switch (pixmap->GetPixelFormat()) {
1585 case PixelFormat::RGB_565:
1586 return Rosen::Drawing::ColorType::COLORTYPE_RGB_565;
1587 case PixelFormat::RGBA_8888:
1588 return Rosen::Drawing::ColorType::COLORTYPE_RGBA_8888;
1589 case PixelFormat::BGRA_8888:
1590 return Rosen::Drawing::ColorType::COLORTYPE_BGRA_8888;
1591 case PixelFormat::ALPHA_8:
1592 return Rosen::Drawing::ColorType::COLORTYPE_ALPHA_8;
1593 case PixelFormat::RGBA_F16:
1594 return Rosen::Drawing::ColorType::COLORTYPE_RGBA_F16;
1595 case PixelFormat::UNKNOWN:
1596 case PixelFormat::ARGB_8888:
1597 case PixelFormat::RGB_888:
1598 case PixelFormat::NV21:
1599 case PixelFormat::NV12:
1600 case PixelFormat::CMYK:
1601 default:
1602 return RSColorType::COLORTYPE_UNKNOWN;
1603 }
1604 }
1605 #endif
1606
1607 void RosenRenderImage::OnAppHide()
1608 {
1609 isAppOnShow_ = false;
1610 if (imageObj_) {
1611 imageObj_->Pause();
1612 }
1613 }
1614
1615 void RosenRenderImage::OnAppShow()
1616 {
1617 isAppOnShow_ = true;
1618 if (imageObj_) {
1619 imageObj_->Resume();
1620 }
1621 }
1622
1623 // pause image when not visible
1624 void RosenRenderImage::OnVisibleChanged()
1625 {
1626 if (imageObj_) {
1627 if (GetVisible()) {
1628 imageObj_->Resume();
1629 } else {
1630 imageObj_->Pause();
1631 }
1632 }
1633 }
1634
1635 #ifndef USE_ROSEN_DRAWING
1636 RefPtr<PixelMap> RosenRenderImage::GetPixmapFromSkImage()
1637 {
1638 auto skImage = AceType::DynamicCast<NG::SkiaImage>(image_);
1639 if (!skImage || !skImage->GetImage()) {
1640 return nullptr;
1641 }
1642 auto image = skImage->GetImage();
1643 auto rasterizedImage = image->makeRasterImage();
1644 SkPixmap srcPixmap;
1645 if (!rasterizedImage->peekPixels(&srcPixmap)) {
1646 return nullptr;
1647 }
1648 SkPixmap newSrcPixmap = CloneSkPixmap(srcPixmap);
1649 auto addr = newSrcPixmap.addr32();
1650 int32_t width = static_cast<int32_t>(newSrcPixmap.width());
1651 int32_t height = static_cast<int32_t>(newSrcPixmap.height());
1652 auto length = width * height;
1653 return PixelMap::ConvertSkImageToPixmap(addr, length, width, height);
1654 }
1655
1656 SkPixmap RosenRenderImage::CloneSkPixmap(SkPixmap& srcPixmap)
1657 {
1658 SkImageInfo dstImageInfo = SkImageInfo::Make(srcPixmap.info().width(), srcPixmap.info().height(),
1659 SkColorType::kBGRA_8888_SkColorType, srcPixmap.alphaType());
1660 auto dstPixels = std::make_unique<uint8_t[]>(srcPixmap.computeByteSize());
1661 SkPixmap dstPixmap(dstImageInfo, dstPixels.release(), srcPixmap.rowBytes());
1662
1663 SkBitmap dstBitmap;
1664 if (!dstBitmap.installPixels(dstPixmap)) {
1665 return dstPixmap;
1666 }
1667 if (!dstBitmap.writePixels(srcPixmap, 0, 0)) {
1668 return dstPixmap;
1669 }
1670 return dstPixmap;
1671 }
1672 #else
1673 RefPtr<PixelMap> RosenRenderImage::GetPixmapFromDrawingImage()
1674 {
1675 auto rosenImage = AceType::DynamicCast<NG::DrawingImage>(image_);
1676 if (!rosenImage || !rosenImage->GetImage()) {
1677 return nullptr;
1678 }
1679 auto rsImage = rosenImage->GetImage();
1680 RSBitmapFormat rsBitmapFormat = { RSColorType::COLORTYPE_BGRA_8888, rsImage->GetAlphaType() };
1681 RSBitmap rsBitmap;
1682 if (!rsBitmap.Build(rsImage->GetWidth(), rsImage->GetHeight(), rsBitmapFormat)) {
1683 LOGW("rsBitmap build fail.");
1684 return nullptr;
1685 }
1686 CHECK_NULL_RETURN(rsImage->ReadPixels(rsBitmap, 0, 0), nullptr);
1687 const auto* addr = static_cast<uint32_t*>(rsBitmap.GetPixels());
1688 auto width = static_cast<int32_t>(rsBitmap.GetWidth());
1689 auto height = static_cast<int32_t>(rsBitmap.GetHeight());
1690 int32_t length = width * height;
1691 return PixelMap::ConvertSkImageToPixmap(addr, length, width, height);
1692 }
1693 #endif
1694 } // namespace OHOS::Ace
1695