#include"lottieview.h" using namespace lottieplayer; static Eina_Bool animator(void *data , double pos) { LottieView *view = static_cast(data); float nextPos = pos + view->mStartPos; if (nextPos > 1.0) nextPos = 1.0; view->seek(nextPos); if (nextPos == 1.0) { view->mAnimator = NULL; view->finished(); return EINA_FALSE; } return EINA_TRUE; } void LottieView::createVgNode(LOTNode *node, Efl_VG *parent) { Efl_VG *shape = evas_vg_shape_add(parent); // update the path const float *data = node->mPath.ptPtr; for(int i=0; i mPath.elmCount; i++) { switch (node->mPath.elmPtr[i]) { case 0: //moveTo { 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; } } if (node->mStroke.enable) { evas_vg_shape_stroke_width_set(shape, node->mStroke.width); //evas_vg_shape_stroke_cap_set(shape, int(node->mStroke.cap)); //evas_vg_shape_stroke_join_set(shape, int(node->mStroke.join)); //evas_vg_shape_stroke_meter_limit_set(shape, node->mStroke.meterLimit); } // update paint info if (node->mType == LOTBrushType::BrushSolid) { int r = (node->mColor.r * node->mColor.a)/255; int g = (node->mColor.g * node->mColor.a)/255; int b = (node->mColor.b * node->mColor.a)/255; 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); } } else if (node->mType == LOTBrushType::BrushGradient) { //TODO fill the gradient info } } void LottieView::update(const std::vector &renderList) { Efl_VG *root = evas_vg_container_add(mVg); for(auto i : renderList) { createVgNode(i, root); } evas_object_vg_root_node_set(mVg, root); } static void mImageDelCb(void *data, Evas *evas, Evas_Object *obj, void *) { LottieView *lottie = (LottieView *)data; if (lottie->mImage != obj) return; lottie->mImage = NULL; lottie->stop(); } static void mVgDelCb(void *data, Evas *evas, Evas_Object *obj, void *) { LottieView *lottie = (LottieView *)data; if (lottie->mVg != obj) return; lottie->mVg = NULL; lottie->stop(); } void LottieView::initializeBufferObject(Evas *evas) { if (mRenderMode) { mImage = evas_object_image_filled_add(evas); evas_object_image_colorspace_set(mImage, EVAS_COLORSPACE_ARGB8888); evas_object_image_alpha_set(mImage, EINA_TRUE); evas_object_event_callback_add(mImage, EVAS_CALLBACK_DEL, mImageDelCb, this); } else { mVg = evas_object_vg_add(evas); evas_object_event_callback_add(mVg, EVAS_CALLBACK_DEL, mVgDelCb, this); } } LottieView::LottieView(Evas *evas, bool renderMode, bool asyncRender):mVg(nullptr), mImage(nullptr) { mPalying = false; mReverse = false; mRepeatCount = 0; mRepeatMode = LottieView::RepeatMode::Restart; mLoop = false; mSpeed = 1; mEvas = evas; mPlayer = new LOTPlayer(); mRenderMode = renderMode; mAsyncRender = asyncRender; initializeBufferObject(evas); } LottieView::~LottieView() { if (mRenderTask.valid()) mRenderTask.get(); if (mAnimator) ecore_animator_del(mAnimator); if (mVg) evas_object_del(mVg); if (mImage) evas_object_del(mImage); delete mPlayer; } Evas_Object *LottieView::getImage() { if (mRenderMode) { return mImage; } else { return mVg; } } void LottieView::show() { if (mRenderMode) { evas_object_show(mImage); } else { evas_object_show(mVg); } seek(0); } void LottieView::hide() { if (mRenderMode) { evas_object_hide(mImage); } else { evas_object_hide(mVg); } } void LottieView::seek(float pos) { if (mPalying && mReverse) pos = 1.0 - pos; mPos = pos; if (mRenderMode) { LOTBuffer buf; evas_object_image_size_get(mImage, &buf.width, &buf.height); if (mAsyncRender) { if (mRenderTask.valid()) return; mDirty = true; buf.buffer = (uint32_t *)evas_object_image_data_get(mImage, EINA_TRUE); buf.bytesPerLine = evas_object_image_stride_get(mImage); mRenderTask = mPlayer->render(mPos, buf); mBuffer = buf; // to force a redraw evas_object_image_data_update_add(mImage, 0 , 0, buf.width, buf.height); } else { buf.buffer = (uint32_t *)evas_object_image_data_get(mImage, EINA_TRUE); buf.bytesPerLine = evas_object_image_stride_get(mImage); bool changed = mPlayer->renderSync(pos, buf); evas_object_image_data_set(mImage, buf.buffer); // if the buffer is updated notify the image object if (changed) { evas_object_image_data_update_add(mImage, 0 , 0, buf.width, buf.height); } } } else { const std::vector &renderList = mPlayer->renderList(pos); update(renderList); } } float LottieView::getPos() { return mPos; } void LottieView::render() { if (!mDirty) return; mDirty = false; if (mRenderMode) { if (!mBuffer.buffer) return; bool changed = false; if (mRenderTask.valid()) { changed = mRenderTask.get(); } evas_object_image_data_set(mImage, mBuffer.buffer); // if the buffer is updated notify the image object if (changed) { evas_object_image_data_update_add(mImage, 0 , 0, mBuffer.width, mBuffer.height); } mBuffer.buffer = nullptr; } else { const std::vector &renderList = mPlayer->renderList(mPos); update(renderList); } } void LottieView::setFilePath(const char *filePath) { mPlayer->setFilePath(filePath); mFrameRate = mPlayer->frameRate(); mTotalFrame = mPlayer->totalFrame(); } void LottieView::setSize(int w, int h) { if (mRenderMode) { evas_object_resize(mImage, w, h); evas_object_image_size_set(mImage, w, h); } else { evas_object_resize(mVg, w, h); } mPlayer->setSize(w, h); } void LottieView::setPos(int x, int y) { if (mRenderMode) { evas_object_move(mImage, x, y); } else { evas_object_move(mVg, x, y); } } void LottieView::finished() { restart(); } void LottieView::loop(bool loop) { mLoop = loop; } void LottieView::setRepeatCount(int count) { mRepeatCount = count; } void LottieView::setRepeatMode(LottieView::RepeatMode mode) { mRepeatMode = mode; } void LottieView::play() { mStartPos = mPos; if (mAnimator) ecore_animator_del(mAnimator); mAnimator = ecore_animator_timeline_add(mPlayer->playTime()/mSpeed, animator, this); mReverse = false; mCurCount = mRepeatCount; mPalying = true; } void LottieView::pause() { } void LottieView::stop() { mPalying = false; if (mAnimator) { ecore_animator_del(mAnimator); mAnimator = NULL; } } void LottieView::restart() { mCurCount--; if (mLoop || mRepeatCount) { if (mRepeatMode == LottieView::RepeatMode::Reverse) mReverse = !mReverse; else mReverse = false; mStartPos = 0; if (mAnimator) ecore_animator_del(mAnimator); mAnimator = ecore_animator_timeline_add(mPlayer->playTime()/mSpeed, animator, this); } }