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