lottie: Added renderTree() api to the lottie animation object. 44/192944/2
authorsubhransu mohanty <sub.mohanty@samsung.com>
Tue, 13 Nov 2018 02:36:34 +0000 (11:36 +0900)
committerHermet Park <chuneon.park@samsung.com>
Thu, 22 Nov 2018 06:30:12 +0000 (06:30 +0000)
Change-Id: I137180d0d46036523357d3b7966dc441b57f9d0c

example/lottieview.cpp
example/lottieview.h
inc/lottieanimation.h
inc/lottiecommon.h
src/lottie/lottieanimation.cpp
src/lottie/lottieitem.cpp
src/lottie/lottieitem.h

index 7072a99..e12653c 100644 (file)
@@ -159,6 +159,46 @@ void LottieView::update(const std::vector<LOTNode *> &renderList)
     evas_object_vg_root_node_set(mVg, root);
 }
 
+void LottieView::updateTree(const LOTLayerNode * node)
+{
+    Efl_VG *root = evas_vg_container_add(mVg);
+    update(node, root);
+    evas_object_vg_root_node_set(mVg, root);
+}
+
+void LottieView::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);
+        }
+    }
+
+    // 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);
+        }
+    }
+}
+
 static void mImageDelCb(void *data, Evas *evas, Evas_Object *obj, void *)
 {
     LottieView *lottie = (LottieView *)data;
@@ -280,8 +320,8 @@ void LottieView::seek(float pos)
             evas_object_image_data_update_add(mImage, 0 , 0, surface.width(), surface.height());
         }
     } else {
-        const std::vector<LOTNode *> &renderList = mPlayer->renderList(mCurFrame, mw, mh);
-        update(renderList);
+        const LOTLayerNode *root = mPlayer->renderTree(mCurFrame, mw, mh);
+        updateTree(root);
     }
 }
 
index 6c3c4ee..cbb0815 100644 (file)
@@ -51,6 +51,8 @@ public:
 private:
     void createVgNode(LOTNode *node, Efl_VG *root);
     void update(const std::vector<LOTNode *> &);
+    void updateTree(const LOTLayerNode *);
+    void update(const LOTLayerNode *, Efl_VG *parent);
     void restart();
 public:
     int                      mw;
index 08edd48..a569c6d 100644 (file)
@@ -29,6 +29,7 @@
 
 class AnimationImpl;
 struct LOTNode;
+struct LOTLayerNode;
 
 namespace lottie {
 
@@ -205,6 +206,18 @@ public:
     const std::vector<LOTNode *> &renderList(size_t frameNo, size_t width, size_t height) const;
 
     /**
+     *  @brief Returns root layer of the composition updated with
+     *         content of the lottie resource at frame number {frameNo}.
+     *
+     *  @param[in] frameNo Content corresponds to the frameno needs to be extracted.
+     *  @param[in] width   content viewbox width
+     *  @param[in] height  content viewbox height
+     *
+     *  @return Root layer node.
+     */
+    const LOTLayerNode * renderTree(size_t frameNo, size_t width, size_t height) const;
+
+    /**
      *  @brief default destructor
      */
     ~Animation();
index 48db67e..75ede5d 100644 (file)
@@ -77,6 +77,57 @@ typedef struct LOTGradientStop
     unsigned char r, g, b, a;
 } LOTGradientStop;
 
+struct LOTNode;
+
+typedef enum
+{
+    MaskModeAdd = 0,
+    MaskModeSubstract,
+    MaskModeIntersect,
+    MaskModeDifference
+} LOTMaskMode;
+
+typedef struct _LOTMask {
+    struct {
+        const float *ptPtr;
+        int          ptCount;
+        const char*  elmPtr;
+        int          elmCount;
+    } mPath;
+    LOTMaskMode mMode;
+}LOTMask;
+
+typedef enum
+{
+    MatteNone = 0,
+    MatteAlpha,
+    MatteAlphaInv,
+    MatteLuma,
+    MatteLumaInv
+} LOTMatteType;
+
+typedef struct LOTLayerNode {
+
+    struct {
+        LOTMask        *ptr;
+        unsigned int    size;
+    }mMaskList;
+
+    struct {
+        LOTLayerNode   **ptr;
+        unsigned int    size;
+    }mLayerList;
+
+    struct {
+        LOTNode       **ptr;
+        unsigned int   size;
+    }mNodeList;
+
+    LOTMatteType mMatte;
+    int          mVisible;
+
+}LOTLayerNode;
+
 typedef struct LOTNode {
 
 #define ChangeFlagNone 0x0000
index 2e9cd17..7fdb861 100644 (file)
@@ -22,6 +22,8 @@ public:
 
     const std::vector<LOTNode *> &
                  renderList(size_t frameNo, const VSize &size);
+    const LOTLayerNode *
+                 renderTree(size_t frameNo, const VSize &size);
 private:
     std::string                  mFilePath;
     std::shared_ptr<LOTModel>    mModel;
@@ -37,6 +39,14 @@ const std::vector<LOTNode *> &AnimationImpl::renderList(size_t frameNo, const VS
     return mCompItem->renderList();
 }
 
+const LOTLayerNode *AnimationImpl::renderTree(size_t frameNo, const VSize &size)
+{
+    if (update(frameNo, size)) {
+       mCompItem->buildRenderTree();
+    }
+    return mCompItem->renderTree();
+}
+
 bool AnimationImpl::update(size_t frameNo, const VSize &size)
 {
    frameNo += mModel->startFrame();
@@ -232,6 +242,12 @@ Animation::renderList(size_t frameNo, size_t width, size_t height) const
     return d->renderList(frameNo, VSize(width, height));
 }
 
+const LOTLayerNode *
+Animation::renderTree(size_t frameNo, size_t width, size_t height) const
+{
+    return d->renderTree(frameNo, VSize(width, height));
+}
+
 std::future<Surface> Animation::render(size_t frameNo, Surface surface)
 {
     return render_scheduler.render(d.get(), frameNo, std::move(surface));
index 009b3ba..648c120 100644 (file)
@@ -106,6 +106,16 @@ const std::vector<LOTNode *> &LOTCompItem::renderList() const
     return mRenderList;
 }
 
+void LOTCompItem::buildRenderTree()
+{
+    mRootLayer->buildLayerNode();
+}
+
+const LOTLayerNode * LOTCompItem::renderTree() const
+{
+    return mRootLayer->layerNode();
+}
+
 bool LOTCompItem::render(const lottie::Surface &surface)
 {
     VBitmap bitmap((uchar *)surface.buffer(), surface.width(), surface.height(),
@@ -159,6 +169,45 @@ VRle LOTMaskItem::rle()
     return mRle;
 }
 
+void LOTLayerItem::buildLayerNode()
+{
+    if (!mLayerCNode) {
+        mLayerCNode = std::make_unique<LOTLayerNode>();
+        mLayerCNode->mMaskList.ptr = nullptr;
+        mLayerCNode->mMaskList.size = 0;
+        mLayerCNode->mLayerList.ptr = nullptr;
+        mLayerCNode->mLayerList.size = 0;
+        mLayerCNode->mNodeList.ptr = nullptr;
+        mLayerCNode->mNodeList.size = 0;
+        mLayerCNode->mMatte = MatteNone;
+        mLayerCNode->mVisible = 0;
+    }
+    mLayerCNode->mVisible = visible();
+    // update matte
+    if (hasMatte()) {
+        switch (mLayerData->mMatteType) {
+        case MatteType::Alpha:
+            mLayerCNode->mMatte = MatteAlpha;
+            break;
+        case MatteType::AlphaInv:
+            mLayerCNode->mMatte = MatteAlphaInv;
+            break;
+        case MatteType::Luma:
+            mLayerCNode->mMatte = MatteLuma;
+            break;
+        case MatteType::LumaInv:
+            mLayerCNode->mMatte = MatteLumaInv;
+            break;
+        default:
+            mLayerCNode->mMatte = MatteNone;
+            break;
+        }
+    }
+    if (hasMask()) {
+        //TODO populate mask property
+    }
+}
+
 void LOTLayerItem::render(VPainter *painter, const VRle &inheritMask, const VRle &inheritMatte, LOTLayerItem *matteSource)
 {
     VRle matteRle;
@@ -351,6 +400,23 @@ void LOTCompLayerItem::updateStaticProperty()
     }
 }
 
+void LOTCompLayerItem::buildLayerNode()
+{
+    LOTLayerItem::buildLayerNode();
+    if (mLayers.size() != mLayersCNode.size()) {
+        for (const auto &layer : mLayers) {
+            layer->buildLayerNode();
+            mLayersCNode.push_back(layer->layerNode());
+        }
+        layerNode()->mLayerList.ptr = mLayersCNode.data();
+        layerNode()->mLayerList.size = mLayersCNode.size();
+    } else {
+        for (const auto &layer : mLayers) {
+            layer->buildLayerNode();
+        }
+    }
+}
+
 void LOTCompLayerItem::render(VPainter *painter, const VRle &inheritMask, const VRle &inheritMatte, LOTLayerItem *matteSource)
 {
     VRle matteRle;
@@ -443,6 +509,23 @@ void LOTSolidLayerItem::updateContent()
     }
 }
 
+void LOTSolidLayerItem::buildLayerNode()
+{
+    LOTLayerItem::buildLayerNode();
+
+    mDrawableList.clear();
+    renderList(mDrawableList);
+
+    mCNodeList.clear();
+    for (auto &i : mDrawableList) {
+        LOTDrawable *lotDrawable = static_cast<LOTDrawable *>(i);
+        lotDrawable->sync();
+        mCNodeList.push_back(lotDrawable->mCNode.get());
+    }
+    layerNode()->mNodeList.ptr = mCNodeList.data();
+    layerNode()->mNodeList.size = mCNodeList.size();
+}
+
 void LOTSolidLayerItem::renderList(std::vector<VDrawable *> &list)
 {
     if (!visible()) return;
@@ -535,6 +618,23 @@ void LOTShapeLayerItem::updateContent()
     }
 }
 
+void LOTShapeLayerItem::buildLayerNode()
+{
+    LOTLayerItem::buildLayerNode();
+
+    mDrawableList.clear();
+    renderList(mDrawableList);
+
+    mCNodeList.clear();
+    for (auto &i : mDrawableList) {
+        LOTDrawable *lotDrawable = static_cast<LOTDrawable *>(i);
+        lotDrawable->sync();
+        mCNodeList.push_back(lotDrawable->mCNode.get());
+    }
+    layerNode()->mNodeList.ptr = mCNodeList.data();
+    layerNode()->mNodeList.size = mCNodeList.size();
+}
+
 void LOTShapeLayerItem::renderList(std::vector<VDrawable *> &list)
 {
     if (!visible()) return;
index 4f14597..a92dd8d 100644 (file)
@@ -38,6 +38,8 @@ public:
    VSize size() const;
    const std::vector<LOTNode *>& renderList()const;
    void buildRenderList();
+   void buildRenderTree();
+   const LOTLayerNode * renderTree()const;
    bool render(const lottie::Surface &surface);
 private:
    VMatrix                                    mScaleMatrix;
@@ -68,7 +70,8 @@ public:
    virtual void render(VPainter *painter, const VRle &mask, const VRle &inheritMatte, LOTLayerItem *matteSource);
    bool hasMatte() { if (mLayerData->mMatteType == MatteType::None) return false; return true; }
    bool visible() const;
-
+   virtual void buildLayerNode();
+   LOTLayerNode * layerNode() const {return mLayerCNode.get();}
 protected:
    virtual void updateContent() = 0;
    inline VMatrix combinedMatrix() const {return mCombinedMatrix;}
@@ -80,6 +83,7 @@ protected:
    VRle maskRle(const VRect &clipRect);
    bool hasMask() const {return !mMasks.empty();}
 protected:
+   std::unique_ptr<LOTLayerNode>               mLayerCNode;
    std::vector<VDrawable *>                    mDrawableList;
    std::vector<std::unique_ptr<LOTMaskItem>>   mMasks;
    LOTLayerData                               *mLayerData{nullptr};
@@ -99,9 +103,11 @@ public:
    void renderList(std::vector<VDrawable *> &list)final;
    void updateStaticProperty() final;
    void render(VPainter *painter, const VRle &mask, const VRle &inheritMatte, LOTLayerItem *matteSource) final;
+   void buildLayerNode() final;
 protected:
    void updateContent() final;
 private:
+   std::vector<LOTLayerNode *>                  mLayersCNode;
    std::vector<std::unique_ptr<LOTLayerItem>>   mLayers;
    int                                          mLastFrame;
 };
@@ -110,10 +116,12 @@ class LOTSolidLayerItem: public LOTLayerItem
 {
 public:
    LOTSolidLayerItem(LOTLayerData *layerData);
+   void buildLayerNode() final;
 protected:
    void updateContent() final;
    void renderList(std::vector<VDrawable *> &list) final;
 private:
+   std::vector<LOTNode *>       mCNodeList;
    std::unique_ptr<VDrawable>   mRenderNode;
 };
 
@@ -125,8 +133,10 @@ public:
    LOTShapeLayerItem(LOTLayerData *layerData);
    static std::unique_ptr<LOTContentItem> createContentItem(LOTData *contentData);
    void renderList(std::vector<VDrawable *> &list)final;
+   void buildLayerNode() final;
 protected:
    void updateContent() final;
+   std::vector<LOTNode *>               mCNodeList;
    std::unique_ptr<LOTContentGroupItem> mRoot;
 };