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