1 /*
2  * Copyright (c) 2022-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_ng/image_provider/image_loading_context.h"
17 
18 #include "base/utils/utils.h"
19 #include "core/components/common/layout/constants.h"
20 #include "core/components_ng/image_provider/image_utils.h"
21 #include "core/components_ng/image_provider/pixel_map_image_object.h"
22 #include "core/components_ng/image_provider/static_image_object.h"
23 #include "core/components_ng/render/image_painter.h"
24 #include "core/image/image_file_cache.h"
25 #include "core/image/image_loader.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27 #ifdef USE_ROSEN_DRAWING
28 #include "core/components_ng/image_provider/adapter/rosen/drawing_image_data.h"
29 #endif
30 
31 namespace OHOS::Ace::NG {
32 
33 namespace {
QueryDataFromCache(const ImageSourceInfo & src,bool & dataHit)34 RefPtr<ImageData> QueryDataFromCache(const ImageSourceInfo& src, bool& dataHit)
35 {
36     ACE_FUNCTION_TRACE();
37 #ifndef USE_ROSEN_DRAWING
38     auto cachedData = ImageLoader::QueryImageDataFromImageCache(src);
39     if (cachedData) {
40         dataHit = true;
41         return NG::ImageData::MakeFromDataWrapper(&cachedData);
42     }
43     auto skData = ImageLoader::LoadDataFromCachedFile(src.GetSrc());
44     if (skData) {
45         sk_sp<SkData> data = SkData::MakeWithCopy(skData->data(), skData->size());
46 
47         return NG::ImageData::MakeFromDataWrapper(&data);
48     }
49 #else
50     std::shared_ptr<RSData> rsData = nullptr;
51     rsData = ImageLoader::QueryImageDataFromImageCache(src);
52     if (rsData) {
53         TAG_LOGD(AceLogTag::ACE_IMAGE, "%{private}s hit the memory Cache.", src.GetSrc().c_str());
54         dataHit = true;
55         return AceType::MakeRefPtr<NG::DrawingImageData>(rsData);
56     }
57     auto drawingData = ImageLoader::LoadDataFromCachedFile(src.GetSrc());
58     if (drawingData) {
59         TAG_LOGD(AceLogTag::ACE_IMAGE, "%{private}s hit the disk Cache, and the data size is %{public}d.",
60             src.GetSrc().c_str(), static_cast<int32_t>(drawingData->GetSize()));
61         auto data = std::make_shared<RSData>();
62         data->BuildWithCopy(drawingData->GetData(), drawingData->GetSize());
63         return AceType::MakeRefPtr<NG::DrawingImageData>(data);
64     }
65 #endif
66     return nullptr;
67 }
68 } // namespace
69 
ImageLoadingContext(const ImageSourceInfo & src,LoadNotifier && loadNotifier,bool syncLoad)70 ImageLoadingContext::ImageLoadingContext(const ImageSourceInfo& src, LoadNotifier&& loadNotifier, bool syncLoad)
71     : src_(src), notifiers_(std::move(loadNotifier)), containerId_(Container::CurrentId()), syncLoad_(syncLoad)
72 {
73     stateManager_ = MakeRefPtr<ImageStateManager>(WeakClaim(this));
74 
75     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) &&
76         src_.GetSrcType() == SrcType::PIXMAP) {
77         syncLoad_ = true;
78     }
79 }
80 
~ImageLoadingContext()81 ImageLoadingContext::~ImageLoadingContext()
82 {
83     if (!syncLoad_) {
84         auto state = stateManager_->GetCurrentState();
85         if (state == ImageLoadingState::DATA_LOADING) {
86             // cancel CreateImgObj task
87             ImageProvider::CancelTask(src_.GetKey(), WeakClaim(this));
88             if (Downloadable()) {
89                 DownloadManager::GetInstance()->RemoveDownloadTask(src_.GetSrc(), nodeId_);
90             }
91         } else if (state == ImageLoadingState::MAKE_CANVAS_IMAGE) {
92             // cancel MakeCanvasImage task
93             if (InstanceOf<StaticImageObject>(imageObj_)) {
94                 ImageProvider::CancelTask(canvasKey_, WeakClaim(this));
95             }
96         }
97     }
98 }
99 
CalculateTargetSize(const SizeF & srcSize,const SizeF & dstSize,const SizeF & rawImageSize)100 SizeF ImageLoadingContext::CalculateTargetSize(const SizeF& srcSize, const SizeF& dstSize, const SizeF& rawImageSize)
101 {
102     if (!srcSize.IsPositive()) {
103         return rawImageSize;
104     }
105 
106     SizeF targetSize = rawImageSize;
107     auto context = PipelineContext::GetCurrentContext();
108     auto viewScale = context ? context->GetViewScale() : 1.0;
109     double widthScale = dstSize.Width() / srcSize.Width() * viewScale;
110     double heightScale = dstSize.Height() / srcSize.Height() * viewScale;
111     if (widthScale < 1.0 && heightScale < 1.0) {
112         targetSize = SizeF(targetSize.Width() * widthScale, targetSize.Height() * heightScale);
113     }
114     return targetSize;
115 }
116 
OnUnloaded()117 void ImageLoadingContext::OnUnloaded()
118 {
119     imageObj_ = nullptr;
120     canvasImage_ = nullptr;
121     srcRect_ = RectF();
122     dstRect_ = RectF();
123     dstSize_ = SizeF();
124 }
125 
OnLoadSuccess()126 void ImageLoadingContext::OnLoadSuccess()
127 {
128     if (DynamicCast<StaticImageObject>(imageObj_)) {
129         imageObj_->ClearData();
130     }
131     if (notifiers_.onLoadSuccess_) {
132         notifiers_.onLoadSuccess_(src_);
133     }
134     ImageUtils::PostToUI(std::move(pendingMakeCanvasImageTask_), "ArkUIImageMakeCanvasImage");
135 }
136 
OnLoadFail()137 void ImageLoadingContext::OnLoadFail()
138 {
139     if (notifiers_.onLoadFail_) {
140         notifiers_.onLoadFail_(src_, errorMsg_);
141     }
142 }
143 
OnDataReady()144 void ImageLoadingContext::OnDataReady()
145 {
146     if (notifiers_.onDataReady_) {
147         notifiers_.onDataReady_(src_);
148     }
149 }
150 
OnDataReadyOnCompleteCallBack()151 void ImageLoadingContext::OnDataReadyOnCompleteCallBack()
152 {
153     if (notifiers_.onDataReadyComplete_) {
154         notifiers_.onDataReadyComplete_(src_);
155     }
156 }
157 
SetOnProgressCallback(std::function<void (const uint32_t & dlNow,const uint32_t & dlTotal)> && onProgress)158 void ImageLoadingContext::SetOnProgressCallback(
159     std::function<void(const uint32_t& dlNow, const uint32_t& dlTotal)>&& onProgress)
160 {
161     onProgressCallback_ = onProgress;
162 }
163 
OnDataLoading()164 void ImageLoadingContext::OnDataLoading()
165 {
166     auto obj = ImageProvider::QueryImageObjectFromCache(src_);
167     if (obj) {
168         TAG_LOGD(AceLogTag::ACE_IMAGE, "%{private}s hit cache, not need create object", src_.GetSrc().c_str());
169         DataReadyCallback(obj);
170         return;
171     }
172     if (Downloadable()) {
173         if (syncLoad_) {
174             DownloadImage();
175         } else {
176             auto task = [weak = AceType::WeakClaim(this)]() {
177                 auto ctx = weak.Upgrade();
178                 CHECK_NULL_VOID(ctx);
179                 ctx->DownloadImage();
180             };
181             NG::ImageUtils::PostToBg(task, "ArkUIImageDownload");
182         }
183         return;
184     }
185     ImageProvider::CreateImageObject(src_, WeakClaim(this), syncLoad_);
186 }
187 
NotifyReadyIfCacheHit()188 bool ImageLoadingContext::NotifyReadyIfCacheHit()
189 {
190     bool dataHit = false;
191     auto cachedImageData = QueryDataFromCache(src_, dataHit);
192     CHECK_NULL_RETURN(cachedImageData, false);
193     auto notifyDataReadyTask = [weak = AceType::WeakClaim(this), data = std::move(cachedImageData), dataHit] {
194         auto ctx = weak.Upgrade();
195         CHECK_NULL_VOID(ctx);
196         auto src = ctx->GetSourceInfo();
197         // if find data or file cache only, build and cache object, cache data if file cache hit
198         RefPtr<ImageObject> imageObj = ImageProvider::BuildImageObject(src, data);
199         ImageProvider::CacheImageObject(imageObj);
200         if (!dataHit) {
201             ImageLoader::CacheImageData(ctx->GetSourceInfo().GetKey(), data);
202         }
203         ctx->DataReadyCallback(imageObj);
204     };
205     if (syncLoad_) {
206         notifyDataReadyTask();
207     } else {
208         ImageUtils::PostToUI(std::move(notifyDataReadyTask), "ArkUIImageNotifyDataReady");
209     }
210     return true;
211 }
212 
Downloadable()213 bool ImageLoadingContext::Downloadable()
214 {
215     return src_.GetSrcType() == SrcType::NETWORK && SystemProperties::GetDownloadByNetworkEnabled();
216 }
217 
DownloadImage()218 void ImageLoadingContext::DownloadImage()
219 {
220     if (NotifyReadyIfCacheHit()) {
221         TAG_LOGD(AceLogTag::ACE_IMAGE, "%{private}s hit the Cache, not need DownLoad.", src_.GetSrc().c_str());
222         return;
223     }
224     PerformDownload();
225 }
226 
PerformDownload()227 void ImageLoadingContext::PerformDownload()
228 {
229     ACE_SCOPED_TRACE("PerformDownload %s", src_.GetSrc().c_str());
230     DownloadCallback downloadCallback;
231     downloadCallback.successCallback = [weak = AceType::WeakClaim(this)](
232                                            const std::string&& imageData, bool async, int32_t instanceId) {
233         ContainerScope scope(instanceId);
234         auto callback = [weak = weak, data = std::move(imageData)]() {
235             auto ctx = weak.Upgrade();
236             CHECK_NULL_VOID(ctx);
237             ctx->DownloadImageSuccess(data);
238         };
239         async ? NG::ImageUtils::PostToUI(callback, "ArkUIImageDownloadSuccess") : callback();
240     };
241     downloadCallback.failCallback = [weak = AceType::WeakClaim(this)](
242                                         std::string errorMessage, bool async, int32_t instanceId) {
243         ContainerScope scope(instanceId);
244         auto callback = [weak = weak, errorMessage = errorMessage]() {
245             auto ctx = weak.Upgrade();
246             CHECK_NULL_VOID(ctx);
247             ctx->DownloadImageFailed(errorMessage);
248         };
249         async ? NG::ImageUtils::PostToUI(callback, "ArkUIImageDownloadFailed") : callback();
250     };
251     downloadCallback.cancelCallback = downloadCallback.failCallback;
252     if (onProgressCallback_) {
253         downloadCallback.onProgressCallback = [weak = AceType::WeakClaim(this)](
254                                                   uint32_t dlTotal, uint32_t dlNow, bool async, int32_t instanceId) {
255             ContainerScope scope(instanceId);
256             auto callback = [weak = weak, dlTotal = dlTotal, dlNow = dlNow]() {
257                 auto ctx = weak.Upgrade();
258                 CHECK_NULL_VOID(ctx);
259                 ctx->DownloadOnProgress(dlNow, dlTotal);
260             };
261             async ? NG::ImageUtils::PostToUI(callback, "ArkUIImageDownloadOnProcess") : callback();
262         };
263     }
264     NetworkImageLoader::DownloadImage(std::move(downloadCallback), src_.GetSrc(), syncLoad_, nodeId_);
265 }
266 
CacheDownloadedImage()267 void ImageLoadingContext::CacheDownloadedImage()
268 {
269     CHECK_NULL_VOID(Downloadable());
270     ImageProvider::CacheImageObject(imageObj_);
271     if (imageObj_->GetData()) {
272         ImageLoader::CacheImageData(GetSourceInfo().GetKey(), imageObj_->GetData());
273     }
274     if (!downloadedUrlData_.empty()) {
275         ImageLoader::WriteCacheToFile(GetSourceInfo().GetSrc(), downloadedUrlData_);
276     }
277 }
278 
DownloadImageSuccess(const std::string & imageData)279 void ImageLoadingContext::DownloadImageSuccess(const std::string& imageData)
280 {
281     TAG_LOGI(AceLogTag::ACE_IMAGE, "Download image successfully, srcInfo = %{private}s, ImageData length=%{public}zu",
282         GetSrc().ToString().c_str(), imageData.size());
283     ACE_LAYOUT_SCOPED_TRACE("DownloadImageSuccess[src:%s]", GetSrc().ToString().c_str());
284     if (!Positive(imageData.size())) {
285         FailCallback("The length of imageData from netStack is not positive");
286         return;
287     }
288     auto data = ImageData::MakeFromDataWithCopy(imageData.data(), imageData.size());
289     // if downloading is necessary, cache object, data to file
290     RefPtr<ImageObject> imageObj = ImageProvider::BuildImageObject(GetSourceInfo(), data);
291     if (!imageObj) {
292         FailCallback("After download successful, imageObject Create fail");
293         return;
294     }
295     downloadedUrlData_ = imageData;
296     DataReadyCallback(imageObj);
297 }
298 
DownloadImageFailed(const std::string & errorMessage)299 void ImageLoadingContext::DownloadImageFailed(const std::string& errorMessage)
300 {
301     TAG_LOGI(AceLogTag::ACE_IMAGE, "Download image failed, the error message is %{private}s", errorMessage.c_str());
302     FailCallback(errorMessage);
303 }
304 
DownloadOnProgress(const uint32_t & dlNow,const uint32_t & dlTotal)305 void ImageLoadingContext::DownloadOnProgress(const uint32_t& dlNow, const uint32_t& dlTotal)
306 {
307     if (onProgressCallback_) {
308         onProgressCallback_(dlNow, dlTotal);
309     }
310 }
311 
OnMakeCanvasImage()312 void ImageLoadingContext::OnMakeCanvasImage()
313 {
314     CHECK_NULL_VOID(imageObj_);
315 
316     // only update params when entered MakeCanvasImage state successfully
317     if (updateParamsCallback_) {
318         updateParamsCallback_();
319         updateParamsCallback_ = nullptr;
320     }
321     auto userDefinedSize = GetSourceSize();
322     SizeF targetSize;
323     if (userDefinedSize) {
324         ImagePainter::ApplyImageFit(imageFit_, *userDefinedSize, dstSize_, srcRect_, dstRect_);
325         targetSize = *userDefinedSize;
326     } else {
327         auto imageSize = GetImageSize();
328         // calculate the srcRect based on original image size
329         ImagePainter::ApplyImageFit(imageFit_, imageSize, dstSize_, srcRect_, dstRect_);
330 
331         bool isPixelMapResource = (SrcType::DATA_ABILITY_DECODED == GetSourceInfo().GetSrcType());
332         if (autoResize_ && !isPixelMapResource) {
333             targetSize = CalculateTargetSize(srcRect_.GetSize(), dstRect_.GetSize(), imageSize);
334             // calculate real srcRect used for paint based on resized image size
335             ImagePainter::ApplyImageFit(imageFit_, targetSize, dstSize_, srcRect_, dstRect_);
336         }
337 
338         // upscale targetSize if size level is mapped
339         if (targetSize.IsPositive() && sizeLevel_ > targetSize.Width()) {
340             targetSize.ApplyScale(sizeLevel_ / targetSize.Width());
341         }
342     }
343 
344     // step4: [MakeCanvasImage] according to [targetSize]
345     canvasKey_ = ImageUtils::GenerateImageKey(src_, targetSize);
346     imageObj_->MakeCanvasImage(Claim(this), targetSize, userDefinedSize.has_value(), syncLoad_, GetLoadInVipChannel());
347 }
348 
ResizableCalcDstSize()349 void ImageLoadingContext::ResizableCalcDstSize()
350 {
351     auto userDefinedSize = GetSourceSize();
352     if (userDefinedSize) {
353         ImagePainter::ApplyImageFit(imageFit_, *userDefinedSize, dstSize_, srcRect_, dstRect_);
354         return;
355     }
356     auto imageSize = GetImageSize();
357     // calculate the srcRect based on original image size
358     ImagePainter::ApplyImageFit(imageFit_, imageSize, dstSize_, srcRect_, dstRect_);
359 
360     bool isPixelMapResource = (SrcType::DATA_ABILITY_DECODED == GetSourceInfo().GetSrcType());
361     if (autoResize_ && !isPixelMapResource) {
362         SizeF targetSize = CalculateTargetSize(srcRect_.GetSize(), dstRect_.GetSize(), imageSize);
363         // calculate real srcRect used for paint based on resized image size
364         ImagePainter::ApplyImageFit(imageFit_, targetSize, dstSize_, srcRect_, dstRect_);
365     }
366 }
367 
DataReadyCallback(const RefPtr<ImageObject> & imageObj)368 void ImageLoadingContext::DataReadyCallback(const RefPtr<ImageObject>& imageObj)
369 {
370     CHECK_NULL_VOID(imageObj);
371     imageObj_ = imageObj->Clone();
372     if (measureFinish_) {
373         OnDataReadyOnCompleteCallBack();
374     } else {
375         needDataReadyCallBack_ = true;
376     }
377     stateManager_->HandleCommand(ImageLoadingCommand::LOAD_DATA_SUCCESS);
378 }
379 
SuccessCallback(const RefPtr<CanvasImage> & canvasImage)380 void ImageLoadingContext::SuccessCallback(const RefPtr<CanvasImage>& canvasImage)
381 {
382     canvasImage_ = canvasImage;
383     CacheDownloadedImage();
384     stateManager_->HandleCommand(ImageLoadingCommand::MAKE_CANVAS_IMAGE_SUCCESS);
385 }
386 
FailCallback(const std::string & errorMsg)387 void ImageLoadingContext::FailCallback(const std::string& errorMsg)
388 {
389     errorMsg_ = errorMsg;
390     needErrorCallBack_ = true;
391     CHECK_NULL_VOID(measureFinish_);
392     TAG_LOGW(AceLogTag::ACE_IMAGE, "Image LoadFail, source = %{private}s, reason: %{public}s", src_.ToString().c_str(),
393         errorMsg.c_str());
394     if (Downloadable()) {
395         ImageFileCache::GetInstance().EraseCacheFile(GetSourceInfo().GetSrc());
396     }
397     stateManager_->HandleCommand(ImageLoadingCommand::LOAD_FAIL);
398     needErrorCallBack_ = false;
399 }
400 
CallbackAfterMeasureIfNeed()401 void ImageLoadingContext::CallbackAfterMeasureIfNeed()
402 {
403     if (needErrorCallBack_) {
404         stateManager_->HandleCommand(ImageLoadingCommand::LOAD_FAIL);
405         needErrorCallBack_ = false;
406     }
407     if (needDataReadyCallBack_) {
408         OnDataReadyOnCompleteCallBack();
409         needDataReadyCallBack_ = false;
410     }
411 }
412 
GetDstRect() const413 const RectF& ImageLoadingContext::GetDstRect() const
414 {
415     return dstRect_;
416 }
417 
GetSrcRect() const418 const RectF& ImageLoadingContext::GetSrcRect() const
419 {
420     return srcRect_;
421 }
422 
MoveCanvasImage()423 RefPtr<CanvasImage> ImageLoadingContext::MoveCanvasImage()
424 {
425     return std::move(canvasImage_);
426 }
427 
MoveImageObject()428 RefPtr<ImageObject> ImageLoadingContext::MoveImageObject()
429 {
430     return std::move(imageObj_);
431 }
432 
LoadImageData()433 void ImageLoadingContext::LoadImageData()
434 {
435     stateManager_->HandleCommand(ImageLoadingCommand::LOAD_DATA);
436 }
437 
RoundUp(int32_t value)438 int32_t ImageLoadingContext::RoundUp(int32_t value)
439 {
440     CHECK_NULL_RETURN(imageObj_, -1);
441     auto res = imageObj_->GetImageSize().Width();
442     CHECK_NULL_RETURN(value > 0 && res > 0, -1);
443     while (res / 2 >= value) {
444         res /= 2;
445     }
446     return res;
447 }
448 
MakeCanvasImageIfNeed(const SizeF & dstSize,bool autoResize,ImageFit imageFit,const std::optional<SizeF> & sourceSize,bool hasValidSlice)449 bool ImageLoadingContext::MakeCanvasImageIfNeed(const SizeF& dstSize, bool autoResize, ImageFit imageFit,
450     const std::optional<SizeF>& sourceSize, bool hasValidSlice)
451 {
452     bool res = autoResize != autoResize_ || imageFit != imageFit_ || sourceSize != GetSourceSize() || firstLoadImage_;
453 
454     /* When function is called with a changed dstSize, assume the image will be resized frequently. To minimize
455      * MakeCanvasImage operations, map dstSize to size levels in log_2. Only Remake when the size level changes.
456      */
457     if (SizeChanging(dstSize)) {
458         res |= RoundUp(dstSize.Width()) != sizeLevel_;
459     } else if (dstSize_ == SizeF()) {
460         res |= dstSize.IsPositive();
461     }
462     if (!res && hasValidSlice) {
463         dstSize_ = dstSize;
464     }
465     CHECK_NULL_RETURN(res, res);
466     if (stateManager_->GetCurrentState() == ImageLoadingState::MAKE_CANVAS_IMAGE) {
467         pendingMakeCanvasImageTask_ = [weak = AceType::WeakClaim(this), dstSize, autoResize, imageFit, sourceSize]() {
468             auto ctx = weak.Upgrade();
469             CHECK_NULL_VOID(ctx);
470             CHECK_NULL_VOID(ctx->SizeChanging(dstSize));
471             ctx->MakeCanvasImage(dstSize, autoResize, imageFit, sourceSize);
472         };
473     } else {
474         MakeCanvasImage(dstSize, autoResize, imageFit, sourceSize);
475     }
476     return res;
477 }
478 
MakeCanvasImage(const SizeF & dstSize,bool autoResize,ImageFit imageFit,const std::optional<SizeF> & sourceSize)479 void ImageLoadingContext::MakeCanvasImage(
480     const SizeF& dstSize, bool autoResize, ImageFit imageFit, const std::optional<SizeF>& sourceSize)
481 {
482     // Because calling of this interface does not guarantee the execution of [MakeCanvasImage], so in order to avoid
483     // updating params before they are not actually used, capture the params in a function. This function will only run
484     // when it actually do [MakeCanvasImage], i.e. doing the update in [OnMakeCanvasImageTask]
485     updateParamsCallback_ = [wp = WeakClaim(this), dstSize, autoResize, imageFit, sourceSize]() {
486         auto ctx = wp.Upgrade();
487         CHECK_NULL_VOID(ctx);
488         if (ctx->SizeChanging(dstSize) || ctx->firstLoadImage_) {
489             ctx->sizeLevel_ = ctx->RoundUp(dstSize.Width());
490         }
491         ctx->firstLoadImage_ = false;
492         ctx->dstSize_ = dstSize;
493         ctx->imageFit_ = imageFit;
494         ctx->autoResize_ = autoResize;
495         ctx->SetSourceSize(sourceSize);
496     };
497     // send command to [StateManager] and waiting the callback from it to determine next step
498     stateManager_->HandleCommand(ImageLoadingCommand::MAKE_CANVAS_IMAGE);
499 }
500 
GetImageSize() const501 SizeF ImageLoadingContext::GetImageSize() const
502 {
503     CHECK_NULL_RETURN(imageObj_, SizeF(-1.0, -1.0));
504     auto imageSize = imageObj_->GetImageSize();
505     auto orientation = imageObj_->GetOrientation();
506     if (orientation == ImageRotateOrientation::LEFT || orientation == ImageRotateOrientation::RIGHT) {
507         return {imageSize.Height(), imageSize.Width()};
508     }
509     return imageSize;
510 }
511 
GetOriginImageSize() const512 SizeF ImageLoadingContext::GetOriginImageSize() const
513 {
514     return imageObj_ ? imageObj_->GetImageSize() : SizeF(-1, -1);
515 }
516 
GetImageFit() const517 ImageFit ImageLoadingContext::GetImageFit() const
518 {
519     return imageFit_;
520 }
521 
SetImageFit(ImageFit imageFit)522 void ImageLoadingContext::SetImageFit(ImageFit imageFit)
523 {
524     imageFit_ = imageFit;
525 }
526 
GetSourceInfo() const527 const ImageSourceInfo& ImageLoadingContext::GetSourceInfo() const
528 {
529     return src_;
530 }
531 
SetAutoResize(bool autoResize)532 void ImageLoadingContext::SetAutoResize(bool autoResize)
533 {
534     autoResize_ = autoResize;
535 }
536 
GetDstSize() const537 const SizeF& ImageLoadingContext::GetDstSize() const
538 {
539     return dstSize_;
540 }
541 
GetAutoResize() const542 bool ImageLoadingContext::GetAutoResize() const
543 {
544     return autoResize_;
545 }
546 
SetSourceSize(const std::optional<SizeF> & sourceSize)547 void ImageLoadingContext::SetSourceSize(const std::optional<SizeF>& sourceSize)
548 {
549     if (sourceSize.has_value()) {
550         sourceSizePtr_ = std::make_unique<SizeF>(sourceSize.value());
551     }
552 }
553 
GetSourceSize() const554 std::optional<SizeF> ImageLoadingContext::GetSourceSize() const
555 {
556     CHECK_NULL_RETURN(sourceSizePtr_, std::nullopt);
557     if (sourceSizePtr_->Width() <= 0.0 || sourceSizePtr_->Height() <= 0.0) {
558         TAG_LOGW(AceLogTag::ACE_IMAGE,
559             "Property SourceSize is at least One invalid! Use the Image Size to calculate resize target");
560         return std::nullopt;
561     }
562     return { *sourceSizePtr_ };
563 }
564 
NeedAlt() const565 bool ImageLoadingContext::NeedAlt() const
566 {
567     auto state = stateManager_->GetCurrentState();
568     return state != ImageLoadingState::LOAD_SUCCESS;
569 }
570 
GetSvgFillColor() const571 const std::optional<Color>& ImageLoadingContext::GetSvgFillColor() const
572 {
573     return src_.GetFillColor();
574 }
575 
ResetLoading()576 void ImageLoadingContext::ResetLoading()
577 {
578     stateManager_->HandleCommand(ImageLoadingCommand::RESET_STATE);
579 }
580 
ResumeLoading()581 void ImageLoadingContext::ResumeLoading()
582 {
583     stateManager_->HandleCommand(ImageLoadingCommand::LOAD_DATA);
584 }
585 
GetCurrentLoadingState()586 const std::string ImageLoadingContext::GetCurrentLoadingState()
587 {
588     ImageLoadingState state = ImageLoadingState::UNLOADED;
589     if (stateManager_) {
590         state = stateManager_->GetCurrentState();
591     }
592     switch (state) {
593         case ImageLoadingState::DATA_LOADING:
594             return "DATA_LOADING";
595         case ImageLoadingState::DATA_READY:
596             return "DATA_READY";
597         case ImageLoadingState::MAKE_CANVAS_IMAGE:
598             return "MAKE_CANVAS_IMAGE";
599         case ImageLoadingState::LOAD_SUCCESS:
600             return "LOAD_SUCCESS";
601         case ImageLoadingState::LOAD_FAIL:
602             return "LOAD_FAIL";
603 
604         default:
605             return "UNLOADED";
606     }
607 }
608 
GetFrameCount() const609 int32_t ImageLoadingContext::GetFrameCount() const
610 {
611     return imageObj_ ? imageObj_->GetFrameCount() : 0;
612 }
613 
614 } // namespace OHOS::Ace::NG
615