From 8e88ee89b88181f8161f11d659411a606ae2fff8 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 7 Nov 2019 15:38:02 +0900 Subject: [PATCH] Example : Update Strategy::eflVg in lottieview The existing Strategy::eflVg make a vector object treeusing a node tree from C++ rlottie API. But it didn't work well. Loading a vector file into evas_object_vg works the same as internally. [Test] Prepare for latest EFL rlottie build ./build/example/lottieviewTest 4 --- example/lottieview.cpp | 3 +- example/lottieview.h | 215 ++++++--------------------------------------- example/lottieviewtest.cpp | 7 +- 3 files changed, 35 insertions(+), 190 deletions(-) diff --git a/example/lottieview.cpp b/example/lottieview.cpp index 05d4bc7..ae5752e 100644 --- a/example/lottieview.cpp +++ b/example/lottieview.cpp @@ -28,7 +28,8 @@ _image_update_cb(void *data, Evas_Object *obj EINA_UNUSED) } void RenderStrategy::addCallback(){ - evas_object_image_pixels_get_callback_set(_renderObject, _image_update_cb, this); + if (_useImage) + evas_object_image_pixels_get_callback_set(_renderObject, _image_update_cb, this); } static Eina_Bool diff --git a/example/lottieview.h b/example/lottieview.h index 5ad3a95..644ba1b 100644 --- a/example/lottieview.h +++ b/example/lottieview.h @@ -43,7 +43,7 @@ public: virtual ~RenderStrategy() { evas_object_del(renderObject()); } - RenderStrategy(Evas_Object *obj):_renderObject(obj){ + RenderStrategy(Evas_Object *obj, bool useImage = true):_renderObject(obj), _useImage(useImage){ addCallback(); } virtual rlottie::Animation *player() {return nullptr;} @@ -55,11 +55,11 @@ public: virtual double duration() = 0; void render(int frame) { _redraw = renderRequest(frame); - if (_redraw) + if (_redraw && _useImage) evas_object_image_pixels_dirty_set(renderObject(), EINA_TRUE); } void dataCb() { - if (_redraw) { + if (_redraw && _useImage) { evas_object_image_data_set(renderObject(), buffer()); } _redraw = false; @@ -78,6 +78,7 @@ protected: private: bool _redraw{false}; Evas_Object *_renderObject; + bool _useImage{true}; }; class CppApiBase : public RenderStrategy { @@ -396,207 +397,49 @@ public: }; #include -class EflVgRenderStrategy : public CppApiBase { - int mW; - int mH; +class EflVgRenderStrategy : public RenderStrategy { public: - EflVgRenderStrategy(Evas *evas):CppApiBase(evas_object_vg_add(evas)) {} + EflVgRenderStrategy(Evas *evas):RenderStrategy(evas_object_vg_add(evas), false) {} - void resize(int width, int height) { - mW = width; - mH = height; - evas_object_resize(renderObject(), width, height); + void loadFromFile(const char *filePath) { + evas_object_vg_file_set(renderObject(), filePath, NULL); } - uint32_t *buffer() { + void loadFromData(const std::string&, const std::string&, const std::string&) { assert(false); } - bool renderRequest(int frame) { - const LOTLayerNode *root = mPlayer->renderTree(frame, mW, mH); - updateTree(root); - return false; + size_t totalFrame() { + return evas_object_vg_animated_frame_count_get(renderObject()) - 1; } - void updateTree(const LOTLayerNode * node) - { - Efl_VG *root = evas_vg_container_add(renderObject()); - update(node, root); - evas_object_vg_root_node_set(renderObject(), root); + double frameRate() { + return (double)totalFrame() / evas_object_vg_animated_frame_duration_get(renderObject(), 0, 0); } - void createVgNode(LOTNode *node, Efl_VG *root) - { - Efl_VG *shape = evas_vg_shape_add(root); - - //0: Path - const float *data = node->mPath.ptPtr; - if (!data) return; - - for (size_t i = 0; i < node->mPath.elmCount; i++) { - switch (node->mPath.elmPtr[i]) { - case 0: - evas_vg_shape_append_move_to(shape, data[0], data[1]); - data += 2; - break; - case 1: - evas_vg_shape_append_line_to(shape, data[0], data[1]); - data += 2; - break; - case 2: - evas_vg_shape_append_cubic_to(shape, data[0], data[1], data[2], data[3], data[4], data[5]); - data += 6; - break; - case 3: - evas_vg_shape_append_close(shape); - break; - default: - break; - } - } - - //1: Stroke - if (node->mStroke.enable) { - //Stroke Width - evas_vg_shape_stroke_width_set(shape, node->mStroke.width); - - //Stroke Cap - Efl_Gfx_Cap cap; - switch (node->mStroke.cap) { - case CapFlat: cap = EFL_GFX_CAP_BUTT; break; - case CapSquare: cap = EFL_GFX_CAP_SQUARE; break; - case CapRound: cap = EFL_GFX_CAP_ROUND; break; - default: cap = EFL_GFX_CAP_BUTT; break; - } - evas_vg_shape_stroke_cap_set(shape, cap); - - //Stroke Join - Efl_Gfx_Join join; - switch (node->mStroke.join) { - case JoinMiter: join = EFL_GFX_JOIN_MITER; break; - case JoinBevel: join = EFL_GFX_JOIN_BEVEL; break; - case JoinRound: join = EFL_GFX_JOIN_ROUND; break; - default: join = EFL_GFX_JOIN_MITER; break; - } - evas_vg_shape_stroke_join_set(shape, join); - - //Stroke Dash - if (node->mStroke.dashArraySize > 0) { - int size = (node->mStroke.dashArraySize / 2); - Efl_Gfx_Dash *dash = static_cast(malloc(sizeof(Efl_Gfx_Dash) * size)); - if (dash) { - for (int i = 0; i <= size; i+=2) { - dash[i].length = node->mStroke.dashArray[i]; - dash[i].gap = node->mStroke.dashArray[i + 1]; - } - evas_vg_shape_stroke_dash_set(shape, dash, size); - free(dash); - } - } - } + size_t frameAtPos(double pos) { + return totalFrame() * pos; + } - //2: Fill Method - switch (node->mBrushType) { - case BrushSolid: { - float pa = ((float)node->mColor.a) / 255; - int r = (int)(((float) node->mColor.r) * pa); - int g = (int)(((float) node->mColor.g) * pa); - int b = (int)(((float) node->mColor.b) * pa); - int a = node->mColor.a; - if (node->mStroke.enable) - evas_vg_shape_stroke_color_set(shape, r, g, b, a); - else - evas_vg_node_color_set(shape, r, g, b, a); - break; - } - case BrushGradient: { - Efl_VG* grad = NULL; - if (node->mGradient.type == GradientLinear) { - grad = evas_vg_gradient_linear_add(root); - evas_vg_gradient_linear_start_set(grad, node->mGradient.start.x, node->mGradient.start.y); - evas_vg_gradient_linear_end_set(grad, node->mGradient.end.x, node->mGradient.end.y); - - } - else if (node->mGradient.type == GradientRadial) { - grad = evas_vg_gradient_radial_add(root); - evas_vg_gradient_radial_center_set(grad, node->mGradient.center.x, node->mGradient.center.y); - evas_vg_gradient_radial_focal_set(grad, node->mGradient.focal.x, node->mGradient.focal.y); - evas_vg_gradient_radial_radius_set(grad, node->mGradient.cradius); - } - - if (grad) { - //Gradient Stop - Efl_Gfx_Gradient_Stop* stops = static_cast(malloc(sizeof(Efl_Gfx_Gradient_Stop) * node->mGradient.stopCount)); - if (stops) { - for (unsigned int i = 0; i < node->mGradient.stopCount; i++) { - stops[i].offset = node->mGradient.stopPtr[i].pos; - float pa = ((float)node->mGradient.stopPtr[i].a) / 255; - stops[i].r = (int)(((float)node->mGradient.stopPtr[i].r) * pa); - stops[i].g = (int)(((float)node->mGradient.stopPtr[i].g) * pa); - stops[i].b = (int)(((float)node->mGradient.stopPtr[i].b) * pa); - stops[i].a = node->mGradient.stopPtr[i].a; - } - evas_vg_gradient_stop_set(grad, stops, node->mGradient.stopCount); - free(stops); - } - if (node->mStroke.enable) - evas_vg_shape_stroke_fill_set(shape, grad); - else - evas_vg_shape_fill_set(shape, grad); - } - break; - } - default: - break; - } + double duration() { + return evas_object_vg_animated_frame_duration_get(renderObject(), 0, 0); + } - //3: Fill Rule -// if (node->mFillRule == FillEvenOdd) -// efl_gfx_shape_fill_rule_set(shape, EFL_GFX_FILL_RULE_ODD_EVEN); -// else if (node->mFillRule == FillWinding) -// efl_gfx_shape_fill_rule_set(shape, EFL_GFX_FILL_RULE_WINDING); + void resize(int width, int height) { + evas_object_resize(renderObject(), width, height); } - void update(const std::vector &renderList) - { - Efl_VG *root = evas_vg_container_add(renderObject()); - for(auto i : renderList) { - createVgNode(i, root); - } - evas_object_vg_root_node_set(renderObject(), root); + uint32_t *buffer() { + assert(false); } - void update(const LOTLayerNode * node, Efl_VG *parent) - { - // if the layer is invisible return - if (!node->mVisible) return; - - // check if this layer is a container layer - bool hasMatte = false; - if (node->mLayerList.size) { - for (unsigned int i = 0; i < node->mLayerList.size; i++) { - if (hasMatte) { - hasMatte = false; - continue; - } - // if the layer has matte then - // the next layer has to be rendered using this layer - // as matte source - if (node->mLayerList.ptr[i]->mMatte != MatteNone) { - hasMatte = true; - printf("Matte is not supported Yet\n"); - continue; - } - update(node->mLayerList.ptr[i], parent); - } - } + bool renderRequest(int frame) { + evas_object_vg_animated_frame_set(renderObject(), frame); + return false; + } - // check if this layer has drawable - if (node->mNodeList.size) { - for (unsigned int i = 0; i < node->mNodeList.size; i++) { - createVgNode(node->mNodeList.ptr[i], parent); - } - } + MarkerFrame findFrameAtMarker(const std::string&) { + return std::make_tuple(0, 0); } }; diff --git a/example/lottieviewtest.cpp b/example/lottieviewtest.cpp index 57cbc71..3d29a4f 100644 --- a/example/lottieviewtest.cpp +++ b/example/lottieviewtest.cpp @@ -103,14 +103,15 @@ main(int argc, char **argv) printf("Run ./lottieviewTest -h for more option\n"); } - EvasApp *app = new EvasApp(800, 800); - app->setup(); - Strategy st = Strategy::renderCppAsync; if (argc > 1) { int option = atoi(argv[1]); st = static_cast(option); } + + EvasApp *app = new EvasApp(800, 800); + app->setup(); + LottieViewTest *view = new LottieViewTest(app, st); view->show(250); -- 2.7.4