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