92eff2310bc8b0eb8f221b9323c6bb3702578b73
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-vector-image / vector-animation-task.h
1 #ifndef DALI_TOOLKIT_VECTOR_ANIMATION_TASK_H
2 #define DALI_TOOLKIT_VECTOR_ANIMATION_TASK_H
3
4 /*
5  * Copyright (c) 2024 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 // EXTERNAL INCLUDES
21 #include <dali/devel-api/adaptor-framework/event-thread-callback.h>
22 #include <dali/devel-api/adaptor-framework/vector-animation-renderer.h>
23 #include <dali/devel-api/threading/mutex.h>
24 #include <dali/public-api/adaptor-framework/async-task-manager.h>
25 #include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
26 #include <dali/public-api/common/vector-wrapper.h>
27 #include <dali/public-api/object/property-array.h>
28 #include <chrono>
29 #include <memory>
30
31 // INTERNAL INCLUDES
32 #include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h>
33 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
34 #include <dali-toolkit/internal/visuals/visual-url.h>
35
36 namespace Dali
37 {
38 namespace Toolkit
39 {
40 namespace Internal
41 {
42 class VisualFactoryCache;
43 class VectorAnimationThread;
44 class VectorAnimationTask;
45 typedef IntrusivePtr<VectorAnimationTask> VectorAnimationTaskPtr;
46
47 /**
48  * The task of the vector animation.
49  */
50 class VectorAnimationTask : public AsyncTask, public ConnectionTracker
51 {
52 public:
53   enum class ResourceStatus
54   {
55     LOADED, /// Resource is loaded
56     READY,  /// Resource is ready
57     FAILED  /// Resource is fail to load
58   };
59
60   using ResourceReadySignalType = Signal<void(ResourceStatus)>;
61
62   using TimePoint           = std::chrono::time_point<std::chrono::steady_clock>;
63   using DynamicPropertyType = std::vector<DevelAnimatedVectorImageVisual::DynamicPropertyInfo>;
64
65   /**
66    * Flags for re-sending data to the vector animation thread
67    */
68   enum ResendFlags
69   {
70     RESEND_PLAY_RANGE                 = 1 << 0,
71     RESEND_LOOP_COUNT                 = 1 << 1,
72     RESEND_STOP_BEHAVIOR              = 1 << 2,
73     RESEND_LOOPING_MODE               = 1 << 3,
74     RESEND_CURRENT_FRAME              = 1 << 4,
75     RESEND_SIZE                       = 1 << 5,
76     RESEND_PLAY_STATE                 = 1 << 6,
77     RESEND_NEED_RESOURCE_READY        = 1 << 7,
78     RESEND_DYNAMIC_PROPERTY           = 1 << 8,
79     RESEND_NOTIFY_AFTER_RASTERIZATION = 1 << 9,
80   };
81
82   /**
83    * @brief Structure used to pass parameters to the vector animation task
84    */
85   struct AnimationData
86   {
87     AnimationData()
88     : resendFlag(0),
89       playRange(),
90       dynamicProperties(),
91       playState(),
92       stopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME),
93       loopingMode(DevelImageVisual::LoopingMode::RESTART),
94       currentFrame(0),
95       width(0),
96       height(0),
97       loopCount(-1),
98       playStateId(0),
99       notifyAfterRasterization(false)
100     {
101     }
102
103     AnimationData& operator=(const AnimationData& rhs)
104     {
105       resendFlag |= rhs.resendFlag; // OR resend flag
106       playRange                = rhs.playRange;
107       playState                = rhs.playState;
108       stopBehavior             = rhs.stopBehavior;
109       loopingMode              = rhs.loopingMode;
110       currentFrame             = rhs.currentFrame;
111       width                    = rhs.width;
112       height                   = rhs.height;
113       loopCount                = rhs.loopCount;
114       playStateId              = rhs.playStateId;
115       notifyAfterRasterization = rhs.notifyAfterRasterization;
116       dynamicProperties.insert(dynamicProperties.end(), rhs.dynamicProperties.begin(), rhs.dynamicProperties.end());
117       return *this;
118     }
119
120     uint32_t                             resendFlag;
121     Property::Array                      playRange;
122     DynamicPropertyType                  dynamicProperties;
123     DevelImageVisual::PlayState::Type    playState;
124     DevelImageVisual::StopBehavior::Type stopBehavior;
125     DevelImageVisual::LoopingMode::Type  loopingMode;
126     uint32_t                             currentFrame;
127     uint32_t                             width;
128     uint32_t                             height;
129     int32_t                              loopCount;
130     uint32_t                             playStateId;
131     bool                                 notifyAfterRasterization;
132   };
133
134   /**
135    * @brief Constructor.
136    *
137    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
138    */
139   VectorAnimationTask(VisualFactoryCache& factoryCache);
140
141   /**
142    * @brief Destructor.
143    */
144   ~VectorAnimationTask() override;
145
146   /**
147    * @brief Finalizes the task.
148    */
149   void Finalize();
150
151   /**
152    * @brief Sets the renderer used to display the result image.
153    *
154    * @param[in] renderer The renderer used to display the result image
155    */
156   void SetRenderer(Renderer renderer);
157
158   /**
159    * @brief Requests to load the animation file.
160    *
161    * @param[in] url The url of the vector animation file
162    * @param[in] encodedImageBuffer The resource buffer if required.
163    * @param[in] synchronousLoading True if the url should be loaded synchronously
164    */
165   void RequestLoad(const VisualUrl& url, EncodedImageBuffer encodedImageBuffer, bool synchronousLoading);
166
167   /**
168    * @brief Queries whether loading is requested.
169    * @return True if loading is requested.
170    */
171   bool IsLoadRequested() const;
172
173   /**
174    * @brief Sets data to specify animation playback.
175    * @param[in] data The animation data
176    */
177   void SetAnimationData(const AnimationData& data);
178
179   /**
180    * @brief This callback is called after the animation is finished.
181    * @param[in] callback The animation finished callback
182    */
183   void SetAnimationFinishedCallback(CallbackBase* callback);
184
185   /**
186    * @brief This callback is called when we want to force render next frame.
187    * @param[in] callback The force render once callback
188    */
189   void SetForceRenderOnceCallback(CallbackBase* callback);
190
191   /**
192    * @brief Gets the playing range in frame number.
193    * @param[out] startFrame The frame number to specify minimum progress.
194    * @param[out] endFrame The frame number to specify maximum progress.
195    */
196   void GetPlayRange(uint32_t& startFrame, uint32_t& endFrame);
197
198   /**
199    * @brief Retrieves the current frame number of the animation.
200    * @return The current frame number
201    */
202   uint32_t GetCurrentFrameNumber() const;
203
204   /**
205    * @brief Retrieves the total frame number of the animation.
206    * @return The total frame number
207    */
208   uint32_t GetTotalFrameNumber() const;
209
210   /**
211    * @brief Gets the default size of the file,.
212    * @return The default size of the file
213    */
214   void GetDefaultSize(uint32_t& width, uint32_t& height) const;
215
216   /**
217    * @brief Gets the layer information of all the child layers.
218    * @param[out] map The layer information
219    */
220   void GetLayerInfo(Property::Map& map) const;
221
222   /**
223    * @brief Gets the all marker information.
224    * @param[out] map The marker information
225    */
226   void GetMarkerInfo(Property::Map& map) const;
227
228   /**
229    * @brief Connect to this signal to be notified when the resource is ready.
230    * @return The signal to connect to.
231    */
232   ResourceReadySignalType& ResourceReadySignal();
233
234   /**
235    * @brief Rasterizes the current frame.
236    * @return true if the rasterization succeeded, false otherwise.
237    */
238   bool Rasterize();
239
240   /**
241    * @brief Calculates the time for the next frame rasterization.
242    * @return The time for the next frame rasterization.
243    */
244   TimePoint CalculateNextFrameTime(bool renderNow);
245
246   /**
247    * @brief Gets the time for the next frame rasterization.
248    * @return The time for the next frame rasterization.
249    */
250   TimePoint GetNextFrameTime();
251
252   /**
253    * @brief Called when the rasterization is completed from the asyncTaskManager
254    * @param[in] task The completed task
255    */
256   void TaskCompleted(VectorAnimationTaskPtr task);
257
258   /**
259    * @brief Check the rasterization succeeded
260    * @return true if the rasterization succeeded, false otherwise.
261    */
262   bool IsRasterized();
263
264   /**
265    * @brief Check the animation is running
266    * @return true if the animation is running, false otherwise.
267    */
268   bool IsAnimating();
269
270   void KeepRasterizedBuffer(bool enableFrameCache)
271   {
272     mEnableFrameCache = enableFrameCache;
273   }
274
275   bool IsKeptRasterizedBuffer() const
276   {
277     return mEnableFrameCache;
278   }
279
280 public: // Implementation of AsyncTask
281   /**
282    * @copydoc Dali::AsyncTask::Process()
283    */
284   void Process() override;
285
286   /**
287    * @copydoc Dali::AsyncTask::IsReady()
288    */
289   bool IsReady() override;
290
291   /**
292    * @copydoc Dali::AsyncTask::GetTaskName()
293    */
294   std::string_view GetTaskName() const override
295   {
296     return "VectorAnimationTask";
297   }
298
299 private:
300   /**
301    * @brief Loads the animation file.
302    *
303    * @param[in] synchronousLoading True if loading is requested synchronously
304    * @return True if loading succeeded, false otherwise.
305    */
306   bool Load(bool synchronousLoading);
307
308   /**
309    * @brief Play the vector animation.
310    */
311   void PlayAnimation();
312
313   /**
314    * @brief Stop the vector animation.
315    */
316   void StopAnimation();
317
318   /**
319    * @brief Pause the vector animation.
320    */
321   void PauseAnimation();
322
323   /**
324    * @brief Sets the target image size.
325    *
326    * @param[in] width The target image width
327    * @param[in] height The target image height
328    */
329   void SetSize(uint32_t width, uint32_t height);
330
331   /**
332    * @brief Enable looping for 'count' repeats. -1 means to repeat forever.
333    * @param[in] count The number of times to loop
334    */
335   void SetLoopCount(int32_t count);
336
337   /**
338    * @brief Set the playing range in frame number.
339    * @param[in] playRange The array to specify minimum and maximum progress.
340    * The animation will play between those values.
341    */
342   void SetPlayRange(const Property::Array& playRange);
343
344   /**
345    * @brief Sets the current frame number of the animation.
346    * @param[in] frameNumber The new frame number between [0, the maximum frame number] or between the play range if specified.
347    */
348   void SetCurrentFrameNumber(uint32_t frameNumber);
349
350   /**
351    * @brief Sets the stop behavior of the animation. This is performed when the animation is stopped.
352    * @param[in] stopBehavior The stop behavior
353    */
354   void SetStopBehavior(DevelImageVisual::StopBehavior::Type stopBehavior);
355
356   /**
357    * @brief Sets the looping mode.
358    * Animation plays forwards and then restarts from the beginning or runs backwards again.
359    * @param[in] loopingMode The looping mode
360    */
361   void SetLoopingMode(DevelImageVisual::LoopingMode::Type loopingMode);
362
363   /**
364    * @brief Gets the frame number when the animation is stopped according to the stop behavior.
365    */
366   uint32_t GetStoppedFrame(uint32_t startFrame, uint32_t endFrame, uint32_t currentFrame);
367
368   /**
369    * @brief Applies the animation data set by the main thread.
370    */
371   void ApplyAnimationData();
372
373   /**
374    * @brief Called when the texture upload is completed.
375    */
376   void OnUploadCompleted();
377
378   /**
379    * @brief Event callback from rasterize thread. This is called when the file loading is completed.
380    */
381   void OnLoadCompleted(uint32_t argument);
382
383   // Undefined
384   VectorAnimationTask(const VectorAnimationTask& task) = delete;
385
386   // Undefined
387   VectorAnimationTask& operator=(const VectorAnimationTask& task) = delete;
388
389 private:
390   enum class PlayState
391   {
392     STOPPING, ///< The animation is stopping
393     STOPPED,  ///< The animation has stopped
394     PLAYING,  ///< The animation is playing
395     PAUSED    ///< The animation is paused
396   };
397
398   VisualUrl                            mImageUrl;
399   EncodedImageBuffer                   mEncodedImageBuffer;
400   VectorAnimationRenderer              mVectorRenderer;
401   std::vector<AnimationData>           mAnimationData[2];
402   VectorAnimationThread&               mVectorAnimationThread;
403   Mutex                                mMutex;
404   ResourceReadySignalType              mResourceReadySignal;
405   std::unique_ptr<CallbackBase>        mAnimationFinishedCallback{};
406   std::unique_ptr<CallbackBase>        mForceRenderOnceCallback{};
407   std::unique_ptr<CallbackBase>        mLoadCompletedCallback{};
408   mutable Property::Map                mCachedLayerInfo;
409   mutable Property::Map                mCachedMarkerInfo;
410   PlayState                            mPlayState;
411   DevelImageVisual::StopBehavior::Type mStopBehavior;
412   DevelImageVisual::LoopingMode::Type  mLoopingMode;
413   TimePoint                            mNextFrameStartTime;
414   int64_t                              mFrameDurationMicroSeconds;
415   float                                mFrameRate;
416   uint32_t                             mCurrentFrame;
417   uint32_t                             mTotalFrame;
418   uint32_t                             mStartFrame;
419   uint32_t                             mEndFrame;
420   uint32_t                             mDroppedFrames;
421   uint32_t                             mWidth;
422   uint32_t                             mHeight;
423   uint32_t                             mAnimationDataIndex;
424   uint32_t                             mAppliedPlayStateId;
425   int32_t                              mLoopCount;
426   int32_t                              mCurrentLoop;
427   bool                                 mForward : 1;
428   bool                                 mUpdateFrameNumber : 1;
429   bool                                 mNeedAnimationFinishedTrigger : 1;
430   bool                                 mNeedForceRenderOnceTrigger : 1;
431   bool                                 mAnimationDataUpdated : 1;
432   bool                                 mDestroyTask : 1;
433   bool                                 mLoadRequest : 1;
434   bool                                 mLoadFailed : 1;
435   bool                                 mRasterized : 1;
436   bool                                 mKeepAnimation : 1;
437   mutable bool                         mLayerInfoCached : 1;
438   mutable bool                         mMarkerInfoCached : 1;
439   bool                                 mEnableFrameCache : 1;
440   bool                                 mNotifyAfterRasterization : 1;
441   bool                                 mSizeUpdated : 1;
442 };
443
444 } // namespace Internal
445
446 } // namespace Toolkit
447
448 } // namespace Dali
449
450 #endif // DALI_TOOLKIT_VECTOR_ANIMATION_TASK_H