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