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