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 <cstdint> 20 #include "base/geometry/ng/size_t.h" 21 #include "base/thread/task_executor.h" 22 #include "core/components/common/layout/constants.h" 23 #include "core/components_ng/image_provider/image_object.h" 24 #include "core/components_ng/image_provider/image_provider.h" 25 #include "core/components_ng/image_provider/image_state_manager.h" 26 27 namespace OHOS::Ace::NG { 28 29 using PendingMakeCanvasImageTask = std::function<void()>; 30 // [ImageLoadingContext] do two things: 31 // 1. Provide interfaces for who owns it, notify it's owner when loading events come. 32 // 2. Drive [ImageObject] to load and make [CanvasImage]. 33 class ACE_FORCE_EXPORT ImageLoadingContext : public AceType { 34 DECLARE_ACE_TYPE(ImageLoadingContext, AceType); 35 36 public: 37 // Create an empty ImageObject and initialize state machine when the constructor is called 38 ImageLoadingContext(const ImageSourceInfo& src, LoadNotifier&& loadNotifier, bool syncLoad = false); 39 ~ImageLoadingContext() override; 40 41 // return true if calling MakeCanvasImage is necessary 42 bool MakeCanvasImageIfNeed(const SizeF& dstSize, bool autoResize, ImageFit imageFit, 43 const std::optional<SizeF>& sourceSize = std::nullopt, bool hasValidSlice = false); 44 45 /* interfaces to drive image loading */ 46 void LoadImageData(); 47 void MakeCanvasImage(const SizeF& dstSize, bool needResize, ImageFit imageFit = ImageFit::COVER, 48 const std::optional<SizeF>& sourceSize = std::nullopt); 49 void ResetLoading(); 50 void ResumeLoading(); 51 52 /* interfaces to get properties */ 53 SizeF GetImageSize() const; 54 SizeF GetOriginImageSize() const; 55 const RectF& GetDstRect() const; 56 const RectF& GetSrcRect() const; 57 ImageFit GetImageFit() const; 58 int32_t GetFrameCount() const; 59 60 RefPtr<CanvasImage> MoveCanvasImage(); 61 RefPtr<ImageObject> MoveImageObject(); GetImageObject()62 RefPtr<ImageObject> GetImageObject() 63 { 64 return imageObj_; 65 } 66 67 const ImageSourceInfo& GetSourceInfo() const; 68 const SizeF& GetDstSize() const; 69 bool GetAutoResize() const; 70 std::optional<SizeF> GetSourceSize() const; 71 bool NeedAlt() const; 72 const std::optional<Color>& GetSvgFillColor() const; 73 74 /* interfaces to set properties */ 75 void SetImageFit(ImageFit imageFit); 76 void SetAutoResize(bool needResize); 77 void SetSourceSize(const std::optional<SizeF>& sourceSize = std::nullopt); GetSrc()78 const ImageSourceInfo GetSrc() const 79 { 80 return src_; 81 } 82 GetStateManger()83 const RefPtr<ImageStateManager>& GetStateManger() 84 { 85 return stateManager_; 86 } 87 88 // callbacks that will be called by ImageProvider when load process finishes 89 void DataReadyCallback(const RefPtr<ImageObject>& imageObj); 90 void SuccessCallback(const RefPtr<CanvasImage>& canvasImage); 91 void FailCallback(const std::string& errorMsg); 92 const std::string GetCurrentLoadingState(); 93 void ResizableCalcDstSize(); 94 // Needed to restore the relevant containerId from the originating thread GetContainerId()95 int32_t GetContainerId() 96 { 97 return containerId_; 98 } 99 void DownloadImage(); 100 void PerformDownload(); 101 void CacheDownloadedImage(); 102 bool Downloadable(); 103 void OnDataReady(); 104 bool RemoveDownloadTask(const std::string& src); 105 FinishMearuse()106 void FinishMearuse() 107 { 108 measureFinish_ = true; 109 } 110 111 void CallbackAfterMeasureIfNeed(); 112 113 void OnDataReadyOnCompleteCallBack(); 114 void SetOnProgressCallback(std::function<void(const uint32_t& dlNow, const uint32_t& dlTotal)>&& onProgress); 115 SetDynamicRangeMode(DynamicRangeMode dynamicMode)116 void SetDynamicRangeMode(DynamicRangeMode dynamicMode) 117 { 118 dynamicMode_ = dynamicMode; 119 } 120 SetIsHdrDecoderNeed(bool isHdrDecoderNeed)121 void SetIsHdrDecoderNeed(bool isHdrDecoderNeed) 122 { 123 isHdrDecoderNeed_ = isHdrDecoderNeed; 124 } 125 GetIsHdrDecoderNeed()126 bool GetIsHdrDecoderNeed() 127 { 128 return isHdrDecoderNeed_; 129 } 130 GetDynamicRangeMode()131 DynamicRangeMode GetDynamicRangeMode() 132 { 133 return dynamicMode_; 134 } 135 SetImageQuality(AIImageQuality imageQuality)136 void SetImageQuality(AIImageQuality imageQuality) 137 { 138 imageQuality_ = imageQuality; 139 } 140 GetImageQuality()141 AIImageQuality GetImageQuality() 142 { 143 return imageQuality_; 144 } 145 GetLoadInVipChannel()146 bool GetLoadInVipChannel() 147 { 148 return loadInVipChannel_; 149 } 150 SetLoadInVipChannel(bool loadInVipChannel)151 void SetLoadInVipChannel(bool loadInVipChannel) 152 { 153 loadInVipChannel_ = loadInVipChannel; 154 } 155 GetErrorMsg()156 const std::string& GetErrorMsg() 157 { 158 return errorMsg_; 159 } 160 SetNodeId(int32_t nodeId)161 void SetNodeId(int32_t nodeId) 162 { 163 nodeId_ = nodeId; 164 } 165 166 private: 167 #define DEFINE_SET_NOTIFY_TASK(loadResult) \ 168 void Set##loadResult##NotifyTask(loadResult##NotifyTask&& loadResult##NotifyTask) \ 169 { \ 170 notifiers_.on##loadResult##_ = std::move(loadResult##NotifyTask); \ 171 } 172 173 // classes that use [ImageLoadingContext] can register three notify tasks to do things 174 DEFINE_SET_NOTIFY_TASK(DataReady); 175 DEFINE_SET_NOTIFY_TASK(LoadSuccess); 176 DEFINE_SET_NOTIFY_TASK(LoadFail); 177 178 // tasks that run when entering a new state 179 void OnUnloaded(); 180 void OnDataLoading(); 181 void OnMakeCanvasImage(); 182 void OnLoadSuccess(); 183 void OnLoadFail(); 184 bool NotifyReadyIfCacheHit(); 185 void DownloadImageSuccess(const std::string& imageData); 186 void DownloadImageFailed(const std::string& errorMessage); 187 void DownloadOnProgress(const uint32_t& dlNow, const uint32_t& dlTotal); 188 // round up int to the nearest 2-fold proportion of image width 189 // REQUIRE: value > 0, image width > 0 190 int32_t RoundUp(int32_t value); 191 static SizeF CalculateTargetSize(const SizeF& srcSize, const SizeF& dstSize, const SizeF& rawImageSize); 192 SizeChanging(const SizeF & dstSize)193 inline bool SizeChanging(const SizeF& dstSize) 194 { 195 return dstSize_.IsPositive() && dstSize != dstSize_; 196 } 197 198 ImageSourceInfo src_; 199 RefPtr<ImageStateManager> stateManager_; 200 RefPtr<ImageObject> imageObj_; 201 RefPtr<CanvasImage> canvasImage_; 202 std::string downloadedUrlData_; 203 204 // [LoadNotifier] contains 3 tasks to notify whom uses [ImageLoadingContext] of loading results 205 LoadNotifier notifiers_; 206 207 // the container of the creator thread of this image loading context 208 const int32_t containerId_ {0}; 209 210 bool autoResize_ = true; 211 bool syncLoad_ = false; 212 bool isHdrDecoderNeed_ = false; 213 bool loadInVipChannel_ = false; 214 215 DynamicRangeMode dynamicMode_ = DynamicRangeMode::STANDARD; 216 AIImageQuality imageQuality_ = AIImageQuality::NONE; 217 218 RectF srcRect_; 219 RectF dstRect_; 220 SizeF dstSize_; 221 std::atomic<bool> measureFinish_ = false; 222 std::atomic<bool> needErrorCallBack_ = false; 223 std::atomic<bool> needDataReadyCallBack_ = false; 224 // to determine whether the image needs to be reloaded 225 int32_t sizeLevel_ = -1; 226 int32_t nodeId_ = -1; 227 228 ImageFit imageFit_ = ImageFit::COVER; 229 std::unique_ptr<SizeF> sourceSizePtr_ = nullptr; 230 std::function<void()> updateParamsCallback_ = nullptr; 231 232 std::string errorMsg_; 233 // to cancel MakeCanvasImage task 234 std::string canvasKey_; 235 236 bool firstLoadImage_ = true; 237 238 // if another makeCanvasImage task arrives and current state cannot handle makeCanvasImage command, 239 // save the least recent makeCanvasImage task and trigger it when the previous makeCanvasImage task end 240 // and state becomes MAKE_CANVAS_IMAGE_SUCCESS 241 PendingMakeCanvasImageTask pendingMakeCanvasImageTask_ = nullptr; 242 243 friend class ImageStateManager; 244 ACE_DISALLOW_COPY_AND_MOVE(ImageLoadingContext); 245 246 std::function<void(const uint32_t& dlNow, const uint32_t& dlTotal)> onProgressCallback_ = nullptr; 247 }; 248 249 } // namespace OHOS::Ace::NG 250 251 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_IMAGE_PROVIDER_IMAGE_LOADING_CONTEXT_H 252