lottie/example: enhanced lottieviewer example
[platform/core/uifw/lottie-player.git] / example / lottieview.cpp
1 #include"lottieview.h"
2
3 using namespace lottieplayer;
4
5 static Eina_Bool
6 animator(void *data , double pos)
7 {
8     LottieView *view = static_cast<LottieView *>(data);
9     float nextPos = pos + view->mStartPos;
10     if (nextPos > 1.0) nextPos = 1.0;
11
12     view->seek(nextPos);
13     if (nextPos == 1.0) {
14       view->mAnimator = NULL;
15       view->finished();
16       return EINA_FALSE;
17     }
18     return EINA_TRUE;
19 }
20
21 void LottieView::createVgNode(LOTNode *node, Efl_VG *parent)
22 {
23     Efl_VG *shape = evas_vg_shape_add(parent);
24     // update the path
25     const float *data = node->mPath.ptPtr;
26     for(int i=0; i <node->mPath.elmCount; i++) {
27         switch (node->mPath.elmPtr[i]) {
28         case 0:  //moveTo
29         {
30             evas_vg_shape_append_move_to(shape, data[0], data[1]);
31             data += 2;
32             break;
33         }
34         case 1:
35         {
36             evas_vg_shape_append_line_to(shape, data[0], data[1]);
37             data += 2;
38             break;
39         }
40         case 2:
41         {
42             evas_vg_shape_append_cubic_to(shape, data[0], data[1], data[2], data[3], data[4], data[5]);
43             data += 6;
44             break;
45         }
46         case 3:
47         {
48             evas_vg_shape_append_close(shape);
49             break;
50         }
51         default:
52             break;
53         }
54     }
55
56     if (node->mStroke.enable) {
57         evas_vg_shape_stroke_width_set(shape, node->mStroke.width);
58         //evas_vg_shape_stroke_cap_set(shape, int(node->mStroke.cap));
59         //evas_vg_shape_stroke_join_set(shape, int(node->mStroke.join));
60         //evas_vg_shape_stroke_meter_limit_set(shape, node->mStroke.meterLimit);
61     }
62     // update paint info
63     if (node->mType == LOTBrushType::BrushSolid) {
64         int r = (node->mColor.r * node->mColor.a)/255;
65         int g = (node->mColor.g * node->mColor.a)/255;
66         int b = (node->mColor.b * node->mColor.a)/255;
67         int a = node->mColor.a;
68         if (node->mStroke.enable) {
69             evas_vg_shape_stroke_color_set(shape, r, g, b, a);
70         } else {
71            evas_vg_node_color_set(shape, r, g, b, a);
72         }
73
74     } else if (node->mType == LOTBrushType::BrushGradient) {
75         //TODO fill the gradient info
76     }
77 }
78
79 void LottieView::update(const std::vector<LOTNode *> &renderList)
80 {
81     Efl_VG *root = evas_vg_container_add(mVg);
82     for(auto i : renderList) {
83         createVgNode(i, root);
84     }
85     evas_object_vg_root_node_set(mVg, root);
86 }
87
88 static void mImageDelCb(void *data, Evas *evas, Evas_Object *obj, void *)
89 {
90     LottieView *lottie = (LottieView *)data;
91
92     if (lottie->mImage != obj) return;
93
94     lottie->mImage = NULL;
95     lottie->stop();
96 }
97
98 static void mVgDelCb(void *data, Evas *evas, Evas_Object *obj, void *)
99 {
100     LottieView *lottie = (LottieView *)data;
101     if (lottie->mVg != obj) return;
102
103     lottie->mVg = NULL;
104     lottie->stop();
105 }
106
107 void LottieView::initializeBufferObject(Evas *evas)
108 {
109     if (mRenderMode) {
110         mImage = evas_object_image_filled_add(evas);
111         evas_object_image_colorspace_set(mImage, EVAS_COLORSPACE_ARGB8888);
112         evas_object_image_alpha_set(mImage, EINA_TRUE);
113         evas_object_event_callback_add(mImage, EVAS_CALLBACK_DEL, mImageDelCb, this);
114     } else {
115         mVg = evas_object_vg_add(evas);
116         evas_object_event_callback_add(mVg, EVAS_CALLBACK_DEL, mVgDelCb, this);
117     }
118 }
119
120 LottieView::LottieView(Evas *evas, bool renderMode, bool asyncRender):mVg(nullptr), mImage(nullptr)
121 {
122     mPalying = false;
123     mReverse = false;
124     mRepeatCount = 0;
125     mRepeatMode = LottieView::RepeatMode::Restart;
126     mLoop = false;
127     mSpeed = 1;
128
129     mEvas = evas;
130     mPlayer = new LOTPlayer();
131     mRenderMode = renderMode;
132     mAsyncRender = asyncRender;
133
134     initializeBufferObject(evas);
135 }
136
137 LottieView::~LottieView()
138 {
139     if (mRenderTask.valid())
140         mRenderTask.get();
141
142     if (mAnimator) ecore_animator_del(mAnimator);
143     if (mVg) evas_object_del(mVg);
144     if (mImage) evas_object_del(mImage);
145     delete mPlayer;
146 }
147
148 Evas_Object *LottieView::getImage() {
149     if (mRenderMode) {
150         return mImage;
151     } else {
152         return mVg;
153     }
154 }
155
156 void LottieView::show()
157 {
158     if (mRenderMode) {
159         evas_object_show(mImage);
160     } else {
161         evas_object_show(mVg);
162     }
163     seek(0);
164 }
165
166 void LottieView::hide()
167 {
168     if (mRenderMode) {
169         evas_object_hide(mImage);
170     } else {
171         evas_object_hide(mVg);
172     }
173 }
174
175 void LottieView::seek(float pos)
176 {
177     if (mPalying && mReverse)
178         pos = 1.0 - pos;
179
180     mPos = pos;
181
182     if (mRenderMode) {
183         LOTBuffer buf;
184         evas_object_image_size_get(mImage, &buf.width, &buf.height);
185         if (mAsyncRender) {
186             if (mRenderTask.valid()) return;
187             mDirty = true;
188             buf.buffer = (uint32_t *)evas_object_image_data_get(mImage, EINA_TRUE);
189             buf.bytesPerLine =  evas_object_image_stride_get(mImage);
190             mRenderTask = mPlayer->render(mPos, buf);
191             mBuffer = buf;
192             // to force a redraw
193             evas_object_image_data_update_add(mImage, 0 , 0, buf.width, buf.height);
194         } else {
195             buf.buffer = (uint32_t *)evas_object_image_data_get(mImage, EINA_TRUE);
196             buf.bytesPerLine =  evas_object_image_stride_get(mImage);
197             bool changed = mPlayer->renderSync(pos, buf);
198             evas_object_image_data_set(mImage, buf.buffer);
199             // if the buffer is updated notify the image object
200             if (changed) {
201                 evas_object_image_data_update_add(mImage, 0 , 0, buf.width, buf.height);
202             }
203         }
204     } else {
205         const std::vector<LOTNode *> &renderList = mPlayer->renderList(pos);
206         update(renderList);
207     }
208 }
209
210 float LottieView::getPos()
211 {
212    return mPos;
213 }
214
215 void LottieView::render()
216 {
217     if (!mDirty) return;
218     mDirty = false;
219
220     if (mRenderMode) {
221         if (!mBuffer.buffer) return;
222         bool changed = false;
223         if (mRenderTask.valid()) {
224             changed = mRenderTask.get();
225         }
226         evas_object_image_data_set(mImage, mBuffer.buffer);
227         // if the buffer is updated notify the image object
228         if (changed) {
229             evas_object_image_data_update_add(mImage, 0 , 0, mBuffer.width, mBuffer.height);
230         }
231         mBuffer.buffer = nullptr;
232     } else {
233         const std::vector<LOTNode *> &renderList = mPlayer->renderList(mPos);
234         update(renderList);
235     }
236 }
237
238 void LottieView::setFilePath(const char *filePath)
239 {
240     mPlayer->setFilePath(filePath);
241     mFrameRate = mPlayer->getFrameRate();
242     mTotalFrame = mPlayer->getTotalFrame();
243 }
244
245 void LottieView::setSize(int w, int h)
246 {
247     if (mRenderMode) {
248         evas_object_resize(mImage, w, h);
249         evas_object_image_size_set(mImage, w, h);
250     } else {
251         evas_object_resize(mVg, w, h);
252     }
253     mPlayer->setSize(w, h);
254 }
255 void LottieView::setPos(int x, int y)
256 {
257     if (mRenderMode) {
258         evas_object_move(mImage, x, y);
259     } else {
260         evas_object_move(mVg, x, y);
261     }
262 }
263
264 void LottieView::finished()
265 {
266     restart();
267 }
268
269 void LottieView::loop(bool loop)
270 {
271     mLoop = loop;
272 }
273
274 void LottieView::setRepeatCount(int count)
275 {
276     mRepeatCount = count;
277 }
278
279 void LottieView::setRepeatMode(LottieView::RepeatMode mode)
280 {
281     mRepeatMode = mode;
282 }
283
284 void LottieView::play()
285 {
286     mStartPos = mPos;
287     if (mAnimator) ecore_animator_del(mAnimator);
288     mAnimator = ecore_animator_timeline_add(mPlayer->playTime()/mSpeed, animator, this);
289     mReverse = false;
290     mCurCount = mRepeatCount;
291     mPalying = true;
292 }
293
294 void LottieView::pause()
295 {
296
297 }
298
299 void LottieView::stop()
300 {
301     mPalying = false;
302     if (mAnimator) {
303         ecore_animator_del(mAnimator);
304         mAnimator = NULL;
305     }
306 }
307
308 void LottieView::restart()
309 {
310     mCurCount--;
311     if (mLoop || mRepeatCount) {
312         if (mRepeatMode == LottieView::RepeatMode::Reverse)
313             mReverse = !mReverse;
314         else
315             mReverse = false;
316
317         mStartPos = 0;
318         if (mAnimator) ecore_animator_del(mAnimator);
319         mAnimator = ecore_animator_timeline_add(mPlayer->playTime()/mSpeed, animator, this);
320     }
321 }