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