[dali_2.3.20] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / image-loader / async-image-loader-impl.cpp
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "async-image-loader-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/adaptor-framework/adaptor.h>
23 #include <dali/public-api/adaptor-framework/async-task-manager.h>
24
25 namespace Dali
26 {
27 namespace Toolkit
28 {
29 namespace Internal
30 {
31 AsyncImageLoader::AsyncImageLoader()
32 : mLoadedSignal(),
33   mLoadTaskId(0u)
34 {
35 }
36
37 AsyncImageLoader::~AsyncImageLoader()
38 {
39   CancelAll();
40 }
41
42 IntrusivePtr<AsyncImageLoader> AsyncImageLoader::New()
43 {
44   IntrusivePtr<AsyncImageLoader> internal = new AsyncImageLoader();
45   return internal;
46 }
47
48 uint32_t AsyncImageLoader::LoadAnimatedImage(Dali::AnimatedImageLoading               animatedImageLoading,
49                                              uint32_t                                 frameIndex,
50                                              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
51 {
52   LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, animatedImageLoading, frameIndex, preMultiplyOnLoad, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
53   Dali::AsyncTaskManager::Get().AddTask(loadingTask);
54   return mLoadTaskId;
55 }
56
57 uint32_t AsyncImageLoader::LoadAnimatedImage(Dali::AnimatedImageLoading               animatedImageLoading,
58                                              uint32_t                                 frameIndex,
59                                              Dali::ImageDimensions                    desiredSize,
60                                              Dali::FittingMode::Type                  fittingMode,
61                                              Dali::SamplingMode::Type                 samplingMode,
62                                              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
63 {
64   LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, animatedImageLoading, frameIndex, desiredSize, fittingMode, samplingMode, preMultiplyOnLoad, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
65   Dali::AsyncTaskManager::Get().AddTask(loadingTask);
66   return mLoadTaskId;
67 }
68
69 uint32_t AsyncImageLoader::Load(const VisualUrl&                         url,
70                                 ImageDimensions                          dimensions,
71                                 FittingMode::Type                        fittingMode,
72                                 SamplingMode::Type                       samplingMode,
73                                 bool                                     orientationCorrection,
74                                 DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
75                                 bool                                     loadPlanes)
76 {
77   LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, url, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, loadPlanes, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
78   AsyncTaskManager::Get().AddTask(loadingTask);
79   mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask, mLoadTaskId));
80   return mLoadTaskId;
81 }
82
83 uint32_t AsyncImageLoader::LoadEncodedImageBuffer(const EncodedImageBuffer&                encodedImageBuffer,
84                                                   ImageDimensions                          dimensions,
85                                                   FittingMode::Type                        fittingMode,
86                                                   SamplingMode::Type                       samplingMode,
87                                                   bool                                     orientationCorrection,
88                                                   DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
89 {
90   LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, encodedImageBuffer, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
91   Dali::AsyncTaskManager::Get().AddTask(loadingTask);
92   mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask, mLoadTaskId));
93   return mLoadTaskId;
94 }
95
96 uint32_t AsyncImageLoader::ApplyMask(Devel::PixelBuffer                       pixelBuffer,
97                                      Devel::PixelBuffer                       maskPixelBuffer,
98                                      float                                    contentScale,
99                                      bool                                     cropToMask,
100                                      DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
101 {
102   LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
103   Dali::AsyncTaskManager::Get().AddTask(loadingTask);
104   mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask, mLoadTaskId));
105   return mLoadTaskId;
106 }
107
108 Toolkit::AsyncImageLoader::ImageLoadedSignalType& AsyncImageLoader::ImageLoadedSignal()
109 {
110   return mLoadedSignal;
111 }
112
113 Toolkit::DevelAsyncImageLoader::PixelBufferLoadedSignalType& AsyncImageLoader::PixelBufferLoadedSignal()
114 {
115   return mPixelBufferLoadedSignal;
116 }
117
118 bool AsyncImageLoader::Cancel(uint32_t loadingTaskId)
119 {
120   // Remove already completed tasks
121   RemoveCompletedTask();
122
123   auto end = mLoadingTasks.end();
124   for(std::vector<AsyncImageLoadingInfo>::iterator iter = mLoadingTasks.begin(); iter != end; ++iter)
125   {
126     if((*iter).loadId == loadingTaskId)
127     {
128       Dali::AsyncTaskManager::Get().RemoveTask((*iter).loadingTask);
129       mLoadingTasks.erase(iter);
130       return true;
131     }
132   }
133
134   return false;
135 }
136
137 void AsyncImageLoader::CancelAll()
138 {
139   // Remove already completed tasks
140   RemoveCompletedTask();
141
142   auto end = mLoadingTasks.end();
143   for(std::vector<AsyncImageLoadingInfo>::iterator iter = mLoadingTasks.begin(); iter != end; ++iter)
144   {
145     if((*iter).loadingTask && Dali::AsyncTaskManager::Get())
146     {
147       Dali::AsyncTaskManager::Get().RemoveTask(((*iter).loadingTask));
148     }
149   }
150   mLoadingTasks.clear();
151 }
152
153 void AsyncImageLoader::ProcessLoadedImage(LoadingTaskPtr task)
154 {
155   if(mPixelBufferLoadedSignal.GetConnectionCount() > 0)
156   {
157     mPixelBufferLoadedSignal.Emit(task->id, task->pixelBuffers);
158   }
159   else if(mLoadedSignal.GetConnectionCount() > 0)
160   {
161     PixelData pixelData;
162     if(!task->pixelBuffers.empty())
163     {
164       pixelData = Devel::PixelBuffer::Convert(task->pixelBuffers[0]);
165     }
166     mLoadedSignal.Emit(task->id, pixelData);
167   }
168
169   mCompletedTaskIds.push_back(task->id);
170 }
171
172 void AsyncImageLoader::RemoveCompletedTask()
173 {
174   std::uint32_t loadingTaskId;
175   auto          end              = mLoadingTasks.end();
176   auto          endCompletedIter = mCompletedTaskIds.end();
177   for(auto iterCompleted = mCompletedTaskIds.begin(); iterCompleted != endCompletedIter; ++iterCompleted)
178   {
179     loadingTaskId = (*iterCompleted);
180     for(std::vector<AsyncImageLoadingInfo>::iterator iter = mLoadingTasks.begin(); iter != end; ++iter)
181     {
182       if((*iter).loadId == loadingTaskId)
183       {
184         mLoadingTasks.erase(iter);
185         end = mLoadingTasks.end();
186         break;
187       }
188     }
189   }
190
191   // Remove cached completed tasks
192   mCompletedTaskIds.clear();
193 }
194
195 } // namespace Internal
196
197 } // namespace Toolkit
198
199 } // namespace Dali