lottieview.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  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. #ifndef LOTTIEVIEW_H
  19. #define LOTTIEVIEW_H
  20. #ifndef EFL_BETA_API_SUPPORT
  21. #define EFL_BETA_API_SUPPORT
  22. #endif
  23. #ifndef EFL_EO_API_SUPPORT
  24. #define EFL_EO_API_SUPPORT
  25. #endif
  26. #include <Eo.h>
  27. #include <Efl.h>
  28. #include <Evas.h>
  29. #include <Ecore.h>
  30. #include <Ecore_Evas.h>
  31. #include "rlottie.h"
  32. #include "rlottie_capi.h"
  33. #include<future>
  34. #include <cmath>
  35. class RenderStrategy {
  36. public:
  37. virtual ~RenderStrategy() {
  38. evas_object_del(renderObject());
  39. }
  40. RenderStrategy(Evas_Object *obj):_renderObject(obj){
  41. addCallback();
  42. }
  43. virtual rlottie::Animation *player() {return nullptr;}
  44. virtual void loadFromFile(const char *filePath) = 0;
  45. virtual void loadFromData(const std::string &jsonData, const std::string &key, const std::string &resourcePath) = 0;
  46. virtual size_t totalFrame() = 0;
  47. virtual double frameRate() = 0;
  48. virtual size_t frameAtPos(double pos) = 0;
  49. virtual double duration() = 0;
  50. void render(int frame) {
  51. _redraw = renderRequest(frame);
  52. if (_redraw)
  53. evas_object_image_pixels_dirty_set(renderObject(), EINA_TRUE);
  54. }
  55. void dataCb() {
  56. if (_redraw) {
  57. evas_object_image_data_set(renderObject(), buffer());
  58. }
  59. _redraw = false;
  60. }
  61. virtual void resize(int width, int height) = 0;
  62. virtual void setPos(int x, int y) {evas_object_move(renderObject(), x, y);}
  63. void show() {evas_object_show(_renderObject);}
  64. void hide() {evas_object_hide(_renderObject);}
  65. void addCallback();
  66. Evas_Object* renderObject() const {return _renderObject;}
  67. protected:
  68. virtual bool renderRequest(int) = 0;
  69. virtual uint32_t* buffer() = 0;
  70. private:
  71. bool _redraw{false};
  72. Evas_Object *_renderObject;
  73. };
  74. class CppApiBase : public RenderStrategy {
  75. public:
  76. CppApiBase(Evas_Object *renderObject): RenderStrategy(renderObject) {}
  77. rlottie::Animation *player() {return mPlayer.get();}
  78. void loadFromFile(const char *filePath)
  79. {
  80. mPlayer = rlottie::Animation::loadFromFile(filePath);
  81. if (!mPlayer) {
  82. printf("load failed file %s\n", filePath);
  83. }
  84. }
  85. void loadFromData(const std::string &jsonData, const std::string &key, const std::string &resourcePath)
  86. {
  87. mPlayer = rlottie::Animation::loadFromData(jsonData, key, resourcePath);
  88. if (!mPlayer) {
  89. printf("load failed from data\n");
  90. }
  91. }
  92. size_t totalFrame() {
  93. return mPlayer->totalFrame();
  94. }
  95. double duration() {
  96. return mPlayer->duration();
  97. }
  98. double frameRate() {
  99. return mPlayer->frameRate();
  100. }
  101. size_t frameAtPos(double pos) {
  102. return mPlayer->frameAtPos(pos);
  103. }
  104. protected:
  105. std::unique_ptr<rlottie::Animation> mPlayer;
  106. };
  107. class RlottieRenderStrategyCBase : public RenderStrategy {
  108. public:
  109. RlottieRenderStrategyCBase(Evas *evas):RenderStrategy(evas_object_image_filled_add(evas)) {
  110. evas_object_image_colorspace_set(renderObject(), EVAS_COLORSPACE_ARGB8888);
  111. evas_object_image_alpha_set(renderObject(), EINA_TRUE);
  112. }
  113. void resize(int width, int height) {
  114. evas_object_resize(renderObject(), width, height);
  115. evas_object_image_size_set(renderObject(), width, height);
  116. }
  117. };
  118. class RlottieRenderStrategy : public CppApiBase {
  119. public:
  120. RlottieRenderStrategy(Evas *evas):CppApiBase(evas_object_image_filled_add(evas)) {
  121. evas_object_image_colorspace_set(renderObject(), EVAS_COLORSPACE_ARGB8888);
  122. evas_object_image_alpha_set(renderObject(), EINA_TRUE);
  123. }
  124. void resize(int width, int height) {
  125. evas_object_resize(renderObject(), width, height);
  126. evas_object_image_size_set(renderObject(), width, height);
  127. }
  128. };
  129. class RlottieRenderStrategy_CPP : public RlottieRenderStrategy {
  130. public:
  131. RlottieRenderStrategy_CPP(Evas *evas):RlottieRenderStrategy(evas) {}
  132. bool renderRequest(int frame) {
  133. int width , height;
  134. Evas_Object *image = renderObject();
  135. evas_object_image_size_get(image, &width, &height);
  136. mBuffer = (uint32_t *)evas_object_image_data_get(image, EINA_TRUE);
  137. size_t bytesperline = evas_object_image_stride_get(image);
  138. rlottie::Surface surface(mBuffer, width, height, bytesperline);
  139. mPlayer->renderSync(frame, surface);
  140. return true;
  141. }
  142. uint32_t* buffer() {
  143. return mBuffer;
  144. }
  145. private:
  146. uint32_t * mBuffer;
  147. };
  148. class RlottieRenderStrategy_CPP_ASYNC : public RlottieRenderStrategy {
  149. public:
  150. RlottieRenderStrategy_CPP_ASYNC(Evas *evas):RlottieRenderStrategy(evas) {}
  151. ~RlottieRenderStrategy_CPP_ASYNC() {
  152. if (mRenderTask.valid())
  153. mRenderTask.get();
  154. }
  155. bool renderRequest(int frame) {
  156. //addCallback();
  157. if (mRenderTask.valid()) return true;
  158. int width , height;
  159. Evas_Object *image = renderObject();
  160. evas_object_image_size_get(image, &width, &height);
  161. auto buffer = (uint32_t *)evas_object_image_data_get(image, EINA_TRUE);
  162. size_t bytesperline = evas_object_image_stride_get(image);
  163. rlottie::Surface surface(buffer, width, height, bytesperline);
  164. mRenderTask = mPlayer->render(frame, surface);
  165. return true;
  166. }
  167. uint32_t* buffer() {
  168. auto surface = mRenderTask.get();
  169. return surface.buffer();
  170. }
  171. private:
  172. std::future<rlottie::Surface> mRenderTask;
  173. };
  174. class RlottieRenderStrategy_C : public RlottieRenderStrategyCBase {
  175. public:
  176. RlottieRenderStrategy_C(Evas *evas):RlottieRenderStrategyCBase(evas) {}
  177. ~RlottieRenderStrategy_C() {
  178. if (mPlayer) lottie_animation_destroy(mPlayer);
  179. }
  180. void loadFromFile(const char *filePath)
  181. {
  182. mPlayer = lottie_animation_from_file(filePath);
  183. if (!mPlayer) {
  184. printf("load failed file %s\n", filePath);
  185. }
  186. }
  187. void loadFromData(const std::string &jsonData, const std::string &key, const std::string &resourcePath)
  188. {
  189. mPlayer = lottie_animation_from_data(jsonData.c_str(), key.c_str(), resourcePath.c_str());
  190. if (!mPlayer) {
  191. printf("load failed from data\n");
  192. }
  193. }
  194. size_t totalFrame() {
  195. return lottie_animation_get_totalframe(mPlayer);
  196. }
  197. double frameRate() {
  198. return lottie_animation_get_framerate(mPlayer);
  199. }
  200. size_t frameAtPos(double pos) {
  201. return lottie_animation_get_frame_at_pos(mPlayer, pos);
  202. }
  203. double duration() {
  204. return lottie_animation_get_duration(mPlayer);
  205. }
  206. bool renderRequest(int frame) {
  207. int width , height;
  208. Evas_Object *image = renderObject();
  209. evas_object_image_size_get(image, &width, &height);
  210. mBuffer = (uint32_t *)evas_object_image_data_get(image, EINA_TRUE);
  211. size_t bytesperline = evas_object_image_stride_get(image);
  212. lottie_animation_render(mPlayer, frame, mBuffer, width, height, bytesperline);
  213. return true;
  214. }
  215. uint32_t* buffer() {
  216. return mBuffer;
  217. }
  218. private:
  219. uint32_t * mBuffer;
  220. protected:
  221. Lottie_Animation *mPlayer;
  222. };
  223. class RlottieRenderStrategy_C_ASYNC : public RlottieRenderStrategy_C {
  224. public:
  225. RlottieRenderStrategy_C_ASYNC(Evas *evas):RlottieRenderStrategy_C(evas) {}
  226. ~RlottieRenderStrategy_C_ASYNC() {
  227. if (mDirty) lottie_animation_render_flush(mPlayer);
  228. }
  229. bool renderRequest(int frame) {
  230. if (mDirty) return true;
  231. mDirty = true;
  232. Evas_Object *image = renderObject();
  233. evas_object_image_size_get(image, &mWidth, &mHeight);
  234. mBuffer = (uint32_t *)evas_object_image_data_get(image, EINA_TRUE);
  235. size_t bytesperline = evas_object_image_stride_get(image);
  236. lottie_animation_render_async(mPlayer, frame, mBuffer, mWidth, mHeight, bytesperline);
  237. return true;
  238. }
  239. uint32_t* buffer() {
  240. lottie_animation_render_flush(mPlayer);
  241. mDirty =false;
  242. return mBuffer;
  243. }
  244. private:
  245. uint32_t * mBuffer;
  246. int mWidth;
  247. int mHeight;
  248. bool mDirty{false};
  249. };
  250. enum class Strategy {
  251. renderCpp = 0,
  252. renderCppAsync,
  253. renderC,
  254. renderCAsync,
  255. eflVg
  256. };
  257. class LottieView
  258. {
  259. public:
  260. enum class RepeatMode {
  261. Restart,
  262. Reverse
  263. };
  264. LottieView(Evas *evas, Strategy s = Strategy::renderCppAsync);
  265. ~LottieView();
  266. rlottie::Animation *player(){return mRenderDelegate->player();}
  267. Evas_Object *getImage();
  268. void setSize(int w, int h);
  269. void setPos(int x, int y);
  270. void setFilePath(const char *filePath);
  271. void loadFromData(const std::string &jsonData, const std::string &key, const std::string &resourcePath="");
  272. void show();
  273. void hide();
  274. void loop(bool loop);
  275. void setSpeed(float speed) { mSpeed = speed;}
  276. void setRepeatCount(int count);
  277. void setRepeatMode(LottieView::RepeatMode mode);
  278. float getFrameRate() const { return mRenderDelegate->frameRate(); }
  279. long getTotalFrame() const { return mRenderDelegate->totalFrame(); }
  280. public:
  281. void seek(float pos);
  282. float getPos();
  283. void finished();
  284. void play();
  285. void pause();
  286. void stop();
  287. void initializeBufferObject(Evas *evas);
  288. void setMinProgress(float progress)
  289. {
  290. //clamp it to [0,1]
  291. mMinProgress = progress;
  292. }
  293. void setMaxProgress(float progress)
  294. {
  295. //clamp it to [0,1]
  296. mMaxprogress = progress;
  297. }
  298. private:
  299. float mapProgress(float progress) {
  300. //clamp it to the segment
  301. progress = (mMinProgress + (mMaxprogress - mMinProgress) * progress);
  302. // currently playing and in reverse mode
  303. if (mPalying && mReverse)
  304. progress = mMaxprogress > mMinProgress ?
  305. mMaxprogress - progress : mMinProgress - progress;
  306. return progress;
  307. }
  308. float duration() const {
  309. // usually we run the animation for mPlayer->duration()
  310. // but now run animation for segmented duration.
  311. return mRenderDelegate->duration() * fabs(mMaxprogress - mMinProgress);
  312. }
  313. void createVgNode(LOTNode *node, Efl_VG *root);
  314. void update(const std::vector<LOTNode *> &);
  315. void updateTree(const LOTLayerNode *);
  316. void update(const LOTLayerNode *, Efl_VG *parent);
  317. void restart();
  318. public:
  319. int mRepeatCount;
  320. LottieView::RepeatMode mRepeatMode;
  321. size_t mCurFrame{UINT_MAX};
  322. Ecore_Animator *mAnimator{nullptr};
  323. bool mLoop;
  324. int mCurCount;
  325. bool mReverse;
  326. bool mPalying;
  327. float mSpeed;
  328. float mPos;
  329. //keep a segment of the animation default is [0, 1]
  330. float mMinProgress{0};
  331. float mMaxprogress{1};
  332. std::unique_ptr<RenderStrategy> mRenderDelegate;
  333. };
  334. #include<assert.h>
  335. class EflVgRenderStrategy : public CppApiBase {
  336. int mW;
  337. int mH;
  338. public:
  339. EflVgRenderStrategy(Evas *evas):CppApiBase(evas_object_vg_add(evas)) {}
  340. void resize(int width, int height) {
  341. mW = width;
  342. mH = height;
  343. evas_object_resize(renderObject(), width, height);
  344. }
  345. uint32_t *buffer() {
  346. assert(false);
  347. }
  348. bool renderRequest(int frame) {
  349. const LOTLayerNode *root = mPlayer->renderTree(frame, mW, mH);
  350. updateTree(root);
  351. return false;
  352. }
  353. void updateTree(const LOTLayerNode * node)
  354. {
  355. Efl_VG *root = evas_vg_container_add(renderObject());
  356. update(node, root);
  357. evas_object_vg_root_node_set(renderObject(), root);
  358. }
  359. void createVgNode(LOTNode *node, Efl_VG *root)
  360. {
  361. Efl_VG *shape = evas_vg_shape_add(root);
  362. //0: Path
  363. const float *data = node->mPath.ptPtr;
  364. if (!data) return;
  365. for (size_t i = 0; i < node->mPath.elmCount; i++) {
  366. switch (node->mPath.elmPtr[i]) {
  367. case 0:
  368. evas_vg_shape_append_move_to(shape, data[0], data[1]);
  369. data += 2;
  370. break;
  371. case 1:
  372. evas_vg_shape_append_line_to(shape, data[0], data[1]);
  373. data += 2;
  374. break;
  375. case 2:
  376. evas_vg_shape_append_cubic_to(shape, data[0], data[1], data[2], data[3], data[4], data[5]);
  377. data += 6;
  378. break;
  379. case 3:
  380. evas_vg_shape_append_close(shape);
  381. break;
  382. default:
  383. break;
  384. }
  385. }
  386. //1: Stroke
  387. if (node->mStroke.enable) {
  388. //Stroke Width
  389. evas_vg_shape_stroke_width_set(shape, node->mStroke.width);
  390. //Stroke Cap
  391. Efl_Gfx_Cap cap;
  392. switch (node->mStroke.cap) {
  393. case CapFlat: cap = EFL_GFX_CAP_BUTT; break;
  394. case CapSquare: cap = EFL_GFX_CAP_SQUARE; break;
  395. case CapRound: cap = EFL_GFX_CAP_ROUND; break;
  396. default: cap = EFL_GFX_CAP_BUTT; break;
  397. }
  398. evas_vg_shape_stroke_cap_set(shape, cap);
  399. //Stroke Join
  400. Efl_Gfx_Join join;
  401. switch (node->mStroke.join) {
  402. case JoinMiter: join = EFL_GFX_JOIN_MITER; break;
  403. case JoinBevel: join = EFL_GFX_JOIN_BEVEL; break;
  404. case JoinRound: join = EFL_GFX_JOIN_ROUND; break;
  405. default: join = EFL_GFX_JOIN_MITER; break;
  406. }
  407. evas_vg_shape_stroke_join_set(shape, join);
  408. //Stroke Dash
  409. if (node->mStroke.dashArraySize > 0) {
  410. int size = (node->mStroke.dashArraySize / 2);
  411. Efl_Gfx_Dash *dash = static_cast<Efl_Gfx_Dash*>(malloc(sizeof(Efl_Gfx_Dash) * size));
  412. if (dash) {
  413. for (int i = 0; i <= size; i+=2) {
  414. dash[i].length = node->mStroke.dashArray[i];
  415. dash[i].gap = node->mStroke.dashArray[i + 1];
  416. }
  417. evas_vg_shape_stroke_dash_set(shape, dash, size);
  418. free(dash);
  419. }
  420. }
  421. }
  422. //2: Fill Method
  423. switch (node->mBrushType) {
  424. case BrushSolid: {
  425. float pa = ((float)node->mColor.a) / 255;
  426. int r = (int)(((float) node->mColor.r) * pa);
  427. int g = (int)(((float) node->mColor.g) * pa);
  428. int b = (int)(((float) node->mColor.b) * pa);
  429. int a = node->mColor.a;
  430. if (node->mStroke.enable)
  431. evas_vg_shape_stroke_color_set(shape, r, g, b, a);
  432. else
  433. evas_vg_node_color_set(shape, r, g, b, a);
  434. break;
  435. }
  436. case BrushGradient: {
  437. Efl_VG* grad = NULL;
  438. if (node->mGradient.type == GradientLinear) {
  439. grad = evas_vg_gradient_linear_add(root);
  440. evas_vg_gradient_linear_start_set(grad, node->mGradient.start.x, node->mGradient.start.y);
  441. evas_vg_gradient_linear_end_set(grad, node->mGradient.end.x, node->mGradient.end.y);
  442. }
  443. else if (node->mGradient.type == GradientRadial) {
  444. grad = evas_vg_gradient_radial_add(root);
  445. evas_vg_gradient_radial_center_set(grad, node->mGradient.center.x, node->mGradient.center.y);
  446. evas_vg_gradient_radial_focal_set(grad, node->mGradient.focal.x, node->mGradient.focal.y);
  447. evas_vg_gradient_radial_radius_set(grad, node->mGradient.cradius);
  448. }
  449. if (grad) {
  450. //Gradient Stop
  451. Efl_Gfx_Gradient_Stop* stops = static_cast<Efl_Gfx_Gradient_Stop*>(malloc(sizeof(Efl_Gfx_Gradient_Stop) * node->mGradient.stopCount));
  452. if (stops) {
  453. for (unsigned int i = 0; i < node->mGradient.stopCount; i++) {
  454. stops[i].offset = node->mGradient.stopPtr[i].pos;
  455. float pa = ((float)node->mGradient.stopPtr[i].a) / 255;
  456. stops[i].r = (int)(((float)node->mGradient.stopPtr[i].r) * pa);
  457. stops[i].g = (int)(((float)node->mGradient.stopPtr[i].g) * pa);
  458. stops[i].b = (int)(((float)node->mGradient.stopPtr[i].b) * pa);
  459. stops[i].a = node->mGradient.stopPtr[i].a;
  460. }
  461. evas_vg_gradient_stop_set(grad, stops, node->mGradient.stopCount);
  462. free(stops);
  463. }
  464. if (node->mStroke.enable)
  465. evas_vg_shape_stroke_fill_set(shape, grad);
  466. else
  467. evas_vg_shape_fill_set(shape, grad);
  468. }
  469. break;
  470. }
  471. default:
  472. break;
  473. }
  474. //3: Fill Rule
  475. // if (node->mFillRule == FillEvenOdd)
  476. // efl_gfx_shape_fill_rule_set(shape, EFL_GFX_FILL_RULE_ODD_EVEN);
  477. // else if (node->mFillRule == FillWinding)
  478. // efl_gfx_shape_fill_rule_set(shape, EFL_GFX_FILL_RULE_WINDING);
  479. }
  480. void update(const std::vector<LOTNode *> &renderList)
  481. {
  482. Efl_VG *root = evas_vg_container_add(renderObject());
  483. for(auto i : renderList) {
  484. createVgNode(i, root);
  485. }
  486. evas_object_vg_root_node_set(renderObject(), root);
  487. }
  488. void update(const LOTLayerNode * node, Efl_VG *parent)
  489. {
  490. // if the layer is invisible return
  491. if (!node->mVisible) return;
  492. // check if this layer is a container layer
  493. bool hasMatte = false;
  494. if (node->mLayerList.size) {
  495. for (unsigned int i = 0; i < node->mLayerList.size; i++) {
  496. if (hasMatte) {
  497. hasMatte = false;
  498. continue;
  499. }
  500. // if the layer has matte then
  501. // the next layer has to be rendered using this layer
  502. // as matte source
  503. if (node->mLayerList.ptr[i]->mMatte != MatteNone) {
  504. hasMatte = true;
  505. printf("Matte is not supported Yet\n");
  506. continue;
  507. }
  508. update(node->mLayerList.ptr[i], parent);
  509. }
  510. }
  511. // check if this layer has drawable
  512. if (node->mNodeList.size) {
  513. for (unsigned int i = 0; i < node->mNodeList.size; i++) {
  514. createVgNode(node->mNodeList.ptr[i], parent);
  515. }
  516. }
  517. }
  518. };
  519. #endif //LOTTIEVIEW_H