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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_IMAGE_PROVIDER_IMAGE_LOADING_CONTEXT_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_IMAGE_PROVIDER_IMAGE_LOADING_CONTEXT_H 18 19 #include "base/geometry/ng/size_t.h" 20 #include "core/components/common/layout/constants.h" 21 #include "core/components_ng/image_provider/image_object.h" 22 #include "core/components_ng/image_provider/image_provider.h" 23 #include "core/components_ng/image_provider/image_state_manager.h" 24 25 namespace OHOS::Ace::NG { 26 27 using PendingMakeCanvasImageTask = std::function<void()>; 28 // [ImageLoadingContext] do two things: 29 // 1. Provide interfaces for who owns it, notify it's owner when loading events come. 30 // 2. Drive [ImageObject] to load and make [CanvasImage]. 31 class ImageLoadingContext : public AceType { 32 DECLARE_ACE_TYPE(ImageLoadingContext, AceType); 33 34 public: 35 // Create an empty ImageObject and initialize state machine when the constructor is called 36 ImageLoadingContext(const ImageSourceInfo& src, LoadNotifier&& loadNotifier, bool syncLoad = false); 37 ~ImageLoadingContext() override; 38 39 // return true if calling MakeCanvasImage is necessary 40 bool MakeCanvasImageIfNeed(const SizeF& dstSize, bool autoResize, ImageFit imageFit, 41 const std::optional<SizeF>& sourceSize = std::nullopt, bool hasValidSlice = false); 42 43 /* interfaces to drive image loading */ 44 void LoadImageData(); 45 void MakeCanvasImage(const SizeF& dstSize, bool needResize, ImageFit imageFit = ImageFit::COVER, 46 const std::optional<SizeF>& sourceSize = std::nullopt); 47 void ResetLoading(); 48 void ResumeLoading(); 49 50 /* interfaces to get properties */ 51 SizeF GetImageSize() const; 52 const RectF& GetDstRect() const; 53 const RectF& GetSrcRect() const; 54 ImageFit GetImageFit() const; 55 int32_t GetFrameCount() const; 56 57 RefPtr<CanvasImage> MoveCanvasImage(); 58 RefPtr<ImageObject> MoveImageObject(); 59 60 const ImageSourceInfo& GetSourceInfo() const; 61 const SizeF& GetDstSize() const; 62 bool GetAutoResize() const; 63 std::optional<SizeF> GetSourceSize() const; 64 bool NeedAlt() const; 65 66 /* interfaces to set properties */ 67 void SetImageFit(ImageFit imageFit); 68 void SetAutoResize(bool needResize); 69 void SetSourceSize(const std::optional<SizeF>& sourceSize = std::nullopt); GetSrc()70 const ImageSourceInfo GetSrc() const 71 { 72 return src_; 73 } 74 GetStateManger()75 const RefPtr<ImageStateManager>& GetStateManger() 76 { 77 return stateManager_; 78 } 79 80 // callbacks that will be called by ImageProvider when load process finishes 81 void DataReadyCallback(const RefPtr<ImageObject>& imageObj); 82 void SuccessCallback(const RefPtr<CanvasImage>& canvasImage); 83 void FailCallback(const std::string& errorMsg); 84 const std::string GetCurrentLoadingState(); 85 void ResizableCalcDstSize(); 86 void DownloadImage(); 87 void PerformDownload(); 88 bool Downloadable(); 89 void OnDataReady(); 90 91 private: 92 #define DEFINE_SET_NOTIFY_TASK(loadResult) \ 93 void Set##loadResult##NotifyTask(loadResult##NotifyTask&& loadResult##NotifyTask) \ 94 { \ 95 notifiers_.on##loadResult##_ = std::move(loadResult##NotifyTask); \ 96 } 97 98 // classes that use [ImageLoadingContext] can register three notify tasks to do things 99 DEFINE_SET_NOTIFY_TASK(DataReady); 100 DEFINE_SET_NOTIFY_TASK(LoadSuccess); 101 DEFINE_SET_NOTIFY_TASK(LoadFail); 102 103 // tasks that run when entering a new state 104 void OnUnloaded(); 105 void OnDataLoading(); 106 void OnMakeCanvasImage(); 107 void OnLoadSuccess(); 108 void OnLoadFail(); 109 bool NotifyReadyIfCacheHit(); 110 void DownloadImageSuccess(const std::string& imageData); 111 void DownloadImageFailed(const std::string& errorMessage); 112 // round up int to the nearest 2-fold proportion of image width 113 // REQUIRE: value > 0, image width > 0 114 int32_t RoundUp(int32_t value); 115 static SizeF CalculateTargetSize(const SizeF& srcSize, const SizeF& dstSize, const SizeF& rawImageSize); 116 SizeChanging(const SizeF & dstSize)117 inline bool SizeChanging(const SizeF& dstSize) 118 { 119 return dstSize_.IsPositive() && dstSize != dstSize_; 120 } 121 122 ImageSourceInfo src_; 123 RefPtr<ImageStateManager> stateManager_; 124 RefPtr<ImageObject> imageObj_; 125 RefPtr<CanvasImage> canvasImage_; 126 127 // [LoadNotifier] contains 3 tasks to notify whom uses [ImageLoadingContext] of loading results 128 LoadNotifier notifiers_; 129 130 bool autoResize_ = true; 131 bool syncLoad_ = false; 132 133 RectF srcRect_; 134 RectF dstRect_; 135 SizeF dstSize_; 136 // to determine whether the image needs to be reloaded 137 int32_t sizeLevel_ = -1; 138 139 ImageFit imageFit_ = ImageFit::COVER; 140 std::unique_ptr<SizeF> sourceSizePtr_ = nullptr; 141 std::function<void()> updateParamsCallback_ = nullptr; 142 143 std::string errorMsg_; 144 // to cancel MakeCanvasImage task 145 std::string canvasKey_; 146 147 // if another makeCanvasImage task arrives and current state cannot handle makeCanvasImage command, 148 // save the least recent makeCanvasImage task and trigger it when the previous makeCanvasImage task end 149 // and state becomes MAKE_CANVAS_IMAGE_SUCCESS 150 PendingMakeCanvasImageTask pendingMakeCanvasImageTask_ = nullptr; 151 152 friend class ImageStateManager; 153 ACE_DISALLOW_COPY_AND_MOVE(ImageLoadingContext); 154 }; 155 156 } // namespace OHOS::Ace::NG 157 158 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_IMAGE_PROVIDER_IMAGE_LOADING_CONTEXT_H 159