lottie: refactor lottie_animation_property_override implementation.
[platform/core/uifw/lottie-player.git] / src / binding / c / lottieanimation_capi.cpp
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 #include "rlottie.h"
20 #include "rlottie_capi.h"
21 #include "vdebug.h"
22
23 using namespace rlottie;
24
25 extern "C" {
26 #include <string.h>
27 #include <stdarg.h>
28
29 struct Lottie_Animation_S
30 {
31     std::unique_ptr<Animation>      mAnimation;
32     std::future<Surface>            mRenderTask;
33     uint32_t                       *mBufferRef;
34     LOTMarkerList                  *mMarkerList;
35 };
36
37 LOT_EXPORT Lottie_Animation_S *lottie_animation_from_file(const char *path)
38 {
39     if (auto animation = Animation::loadFromFile(path) ) {
40         Lottie_Animation_S *handle = new Lottie_Animation_S();
41         handle->mAnimation = std::move(animation);
42         return handle;
43     } else {
44         return nullptr;
45     }
46 }
47
48 LOT_EXPORT Lottie_Animation_S *lottie_animation_from_data(const char *data, const char *key, const char *resourcePath)
49 {
50     if (auto animation = Animation::loadFromData(data, key, resourcePath) ) {
51         Lottie_Animation_S *handle = new Lottie_Animation_S();
52         handle->mAnimation = std::move(animation);
53         return handle;
54     } else {
55         return nullptr;
56     }
57 }
58
59 LOT_EXPORT void lottie_animation_destroy(Lottie_Animation_S *animation)
60 {
61     if (animation) {
62         if (animation->mMarkerList) {
63             for(size_t i = 0; i < animation->mMarkerList->size; i++) {
64                 if (animation->mMarkerList->ptr[i].name) free(animation->mMarkerList->ptr[i].name);
65             }
66             delete[] animation->mMarkerList->ptr;
67             delete animation->mMarkerList;
68         }
69
70         if (animation->mRenderTask.valid()) {
71             animation->mRenderTask.get();
72         }
73         animation->mAnimation = nullptr;
74         delete animation;
75     }
76 }
77
78 LOT_EXPORT void lottie_animation_get_size(const Lottie_Animation_S *animation, size_t *width, size_t *height)
79 {
80    if (!animation) return;
81
82    animation->mAnimation->size(*width, *height);
83 }
84
85 LOT_EXPORT double lottie_animation_get_duration(const Lottie_Animation_S *animation)
86 {
87    if (!animation) return 0;
88
89    return animation->mAnimation->duration();
90 }
91
92 LOT_EXPORT size_t lottie_animation_get_totalframe(const Lottie_Animation_S *animation)
93 {
94    if (!animation) return 0;
95
96    return animation->mAnimation->totalFrame();
97 }
98
99
100 LOT_EXPORT double lottie_animation_get_framerate(const Lottie_Animation_S *animation)
101 {
102    if (!animation) return 0;
103
104    return animation->mAnimation->frameRate();
105 }
106
107 LOT_EXPORT const LOTLayerNode * lottie_animation_render_tree(Lottie_Animation_S *animation, size_t frame_num, size_t width, size_t height)
108 {
109     if (!animation) return nullptr;
110
111     return animation->mAnimation->renderTree(frame_num, width, height);
112 }
113
114 LOT_EXPORT size_t
115 lottie_animation_get_frame_at_pos(const Lottie_Animation_S *animation, float pos)
116 {
117     if (!animation) return 0;
118
119     return animation->mAnimation->frameAtPos(pos);
120 }
121
122 LOT_EXPORT void
123 lottie_animation_render(Lottie_Animation_S *animation,
124                         size_t frame_number,
125                         uint32_t *buffer,
126                         size_t width,
127                         size_t height,
128                         size_t bytes_per_line)
129 {
130     if (!animation) return;
131
132     rlottie::Surface surface(buffer, width, height, bytes_per_line);
133     animation->mAnimation->renderSync(frame_number, surface);
134 }
135
136 LOT_EXPORT void
137 lottie_animation_render_async(Lottie_Animation_S *animation,
138                               size_t frame_number,
139                               uint32_t *buffer,
140                               size_t width,
141                               size_t height,
142                               size_t bytes_per_line)
143 {
144     if (!animation) return;
145
146     rlottie::Surface surface(buffer, width, height, bytes_per_line);
147     animation->mRenderTask = animation->mAnimation->render(frame_number, surface);
148     animation->mBufferRef = buffer;
149 }
150
151 LOT_EXPORT uint32_t *
152 lottie_animation_render_flush(Lottie_Animation_S *animation)
153 {
154     if (!animation) return nullptr;
155
156     if (animation->mRenderTask.valid()) {
157         animation->mRenderTask.get();
158     }
159
160     return animation->mBufferRef;
161 }
162
163 LOT_EXPORT void
164 lottie_animation_property_override(Lottie_Animation_S *animation,
165                                    const Lottie_Animation_Property type,
166                                    const char *keypath,
167                                    ...)
168 {
169     va_list prop;
170     va_start(prop, keypath);
171     const int arg_count = [type](){
172                              switch (type) {
173                               case LOTTIE_ANIMATION_PROPERTY_FILLCOLOR:
174                               case LOTTIE_ANIMATION_PROPERTY_STROKECOLOR:
175                                 return 3;
176                               case LOTTIE_ANIMATION_PROPERTY_FILLOPACITY:
177                               case LOTTIE_ANIMATION_PROPERTY_STROKEOPACITY:
178                               case LOTTIE_ANIMATION_PROPERTY_STROKEWIDTH:
179                               case LOTTIE_ANIMATION_PROPERTY_TR_ROTATION:
180                                 return 1;
181                               case LOTTIE_ANIMATION_PROPERTY_TR_POSITION:
182                               case LOTTIE_ANIMATION_PROPERTY_TR_SCALE:
183                                 return 2;
184                               default:
185                                 return 0;
186                              }
187                           }();
188     double v[3] = {0};
189     for (int i = 0; i < arg_count ; i++) {
190       v[i] = va_arg(prop, double);
191     }
192     va_end(prop);
193
194     switch(type) {
195     case LOTTIE_ANIMATION_PROPERTY_FILLCOLOR: {
196         double r = v[0];
197         double g = v[1];
198         double b = v[2];
199         if (r > 1 || r < 0 || g > 1 || g < 0 || b > 1 || b < 0) break;
200         animation->mAnimation->setValue<rlottie::Property::FillColor>(keypath, rlottie::Color(r, g, b));
201         break;
202     }
203     case LOTTIE_ANIMATION_PROPERTY_FILLOPACITY: {
204         double opacity = v[0];
205         if (opacity > 100 || opacity < 0) break;
206         animation->mAnimation->setValue<rlottie::Property::FillOpacity>(keypath, (float)opacity);
207         break;
208     }
209     case LOTTIE_ANIMATION_PROPERTY_STROKECOLOR: {
210         double r = v[0];
211         double g = v[1];
212         double b = v[2];
213         if (r > 1 || r < 0 || g > 1 || g < 0 || b > 1 || b < 0) break;
214         animation->mAnimation->setValue<rlottie::Property::StrokeColor>(keypath, rlottie::Color(r, g, b));
215         break;
216     }
217     case LOTTIE_ANIMATION_PROPERTY_STROKEOPACITY: {
218         double opacity = v[0];
219         if (opacity > 100 || opacity < 0) break;
220         animation->mAnimation->setValue<rlottie::Property::StrokeOpacity>(keypath, (float)opacity);
221         break;
222     }
223     case LOTTIE_ANIMATION_PROPERTY_STROKEWIDTH: {
224         double width = v[0];
225         if (width < 0) break;
226         animation->mAnimation->setValue<rlottie::Property::StrokeWidth>(keypath, (float)width);
227         break;
228     }
229     case LOTTIE_ANIMATION_PROPERTY_TR_POSITION: {
230         double x = v[0];
231         double y = v[1];
232         animation->mAnimation->setValue<rlottie::Property::TrPosition>(keypath, rlottie::Point((float)x, (float)y));
233         break;
234     }
235     case LOTTIE_ANIMATION_PROPERTY_TR_SCALE: {
236         double w = v[0];
237         double h = v[1];
238         animation->mAnimation->setValue<rlottie::Property::TrScale>(keypath, rlottie::Size((float)w, (float)h));
239         break;
240     }
241     case LOTTIE_ANIMATION_PROPERTY_TR_ROTATION: {
242         double r = v[0];
243         animation->mAnimation->setValue<rlottie::Property::TrRotation>(keypath, (float)r);
244         break;
245     }
246     case LOTTIE_ANIMATION_PROPERTY_TR_ANCHOR:
247     case LOTTIE_ANIMATION_PROPERTY_TR_OPACITY:
248         //@TODO handle propery update.
249         break;
250     }
251 }
252
253 LOT_EXPORT const LOTMarkerList*
254 lottie_animation_get_markerlist(Lottie_Animation_S *animation)
255 {
256    if (!animation) return nullptr;
257
258    auto markers = animation->mAnimation->markers();
259    if (markers.size() == 0) return nullptr;
260    if (animation->mMarkerList) return (const LOTMarkerList*)animation->mMarkerList;
261
262    animation->mMarkerList = new LOTMarkerList();
263    animation->mMarkerList->size = markers.size();
264    animation->mMarkerList->ptr = new LOTMarker[markers.size()]();
265
266    for(size_t i = 0; i < markers.size(); i++) {
267        animation->mMarkerList->ptr[i].name = strdup(std::get<0>(markers[i]).c_str());
268        animation->mMarkerList->ptr[i].startframe= std::get<1>(markers[i]);
269        animation->mMarkerList->ptr[i].endframe= std::get<2>(markers[i]);
270    }
271    return (const LOTMarkerList*)animation->mMarkerList;
272 }
273
274 }