rlottie: refactor Pathitem Object to keep 2 path objects instead of 3.
authorsubhransu mohanty <sub.mohanty@samsung.com>
Tue, 22 Oct 2019 04:12:01 +0000 (13:12 +0900)
committerJunsuChoi <jsuya.choi@samsung.com>
Wed, 13 Nov 2019 00:44:45 +0000 (09:44 +0900)
src/lottie/lottieitem.cpp
src/lottie/lottieitem.h
src/vector/vpath.cpp
src/vector/vpath.h

index e75bca7..6f9c584 100644 (file)
@@ -1015,21 +1015,26 @@ void LOTContentGroupItem::processTrimItems(std::vector<LOTPathDataItem *> &list)
 }
 
 /*
- * LOTPathDataItem uses 3 path objects for path object reuse.
+ * LOTPathDataItem uses 2 path objects for path object reuse.
  * mLocalPath -  keeps track of the local path of the item before
  * applying path operation and transformation.
  * mTemp - keeps a referece to the mLocalPath and can be updated by the
  *          path operation objects(trim, merge path),
- *  mFinalPath - it takes a deep copy of the intermediate path(mTemp) each time
- *  when the path is dirty(so if path changes every frame we don't realloc just
- * copy to the final path). NOTE: As path objects are COW objects we have to be
+ * We update the DirtyPath flag if the path needs to be updated again
+ * beacuse of local path or matrix or some path operation has changed which
+ * affects the final path.
+ * The PaintObject queries the dirty flag to check if it needs to compute the
+ * final path again and calls finalPath() api to do the same.
+ * finalPath() api passes a result Object so that we keep only one copy of
+ * the path object in the paintItem (for memory efficiency).
+ *   NOTE: As path objects are COW objects we have to be
  * carefull about the refcount so that we don't generate deep copy while
  * modifying the path objects.
  */
 void LOTPathDataItem::update(int              frameNo, const VMatrix &, float,
                              const DirtyFlag &flag)
 {
-    mPathChanged = false;
+    mDirtyPath = false;
 
     // 1. update the local path if needed
     if (hasChanged(frameNo)) {
@@ -1038,30 +1043,24 @@ void LOTPathDataItem::update(int              frameNo, const VMatrix &, float,
         mTemp = VPath();
 
         updatePath(mLocalPath, frameNo);
-        mPathChanged = true;
-        mNeedUpdate = true;
+        mDirtyPath = true;
     }
     // 2. keep a reference path in temp in case there is some
     // path operation like trim which will update the path.
     // we don't want to update the local path.
     mTemp = mLocalPath;
 
-    // 3. compute the final path with parentMatrix
-    if ((flag & DirtyFlagBit::Matrix) || mPathChanged) {
-        mPathChanged = true;
+    // 3. mark the path dirty if matrix has changed.
+    if (flag & DirtyFlagBit::Matrix) {
+        mDirtyPath = true;
     }
 }
 
-const VPath &LOTPathDataItem::finalPath()
+void LOTPathDataItem::finalPath(VPath& result)
 {
-    if (mPathChanged || mNeedUpdate) {
-        mFinalPath.clone(mTemp);
-        mFinalPath.transform(
-            static_cast<LOTContentGroupItem *>(parent())->matrix());
-        mNeedUpdate = false;
-    }
-    return mFinalPath;
+    result.addPath(mTemp, static_cast<LOTContentGroupItem *>(parent())->matrix());
 }
+
 LOTRectItem::LOTRectItem(LOTRectData *data)
     : LOTPathDataItem(data->isStatic()), mData(data)
 {
@@ -1162,11 +1161,10 @@ void LOTPaintDataItem::updateRenderNode()
         }
     }
 
-    if (dirty || mPath.empty()) {
+    if (dirty) {
         mPath.reset();
-
-        for (auto &i : mPathItems) {
-            mPath.addPath(i->finalPath());
+        for (const auto &i : mPathItems) {
+            i->finalPath(mPath);
         }
         mDrawable.setPath(mPath);
     } else {
index df20910..0ed30ce 100644 (file)
@@ -355,10 +355,10 @@ public:
    LOTPathDataItem(bool staticPath): mStaticPath(staticPath){}
    void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final;
    ContentType type() const final {return ContentType::Path;}
-   bool dirty() const {return mPathChanged;}
+   bool dirty() const {return mDirtyPath;}
    const VPath &localPath() const {return mTemp;}
-   const VPath &finalPath();
-   void updatePath(const VPath &path) {mTemp = path; mPathChanged = true; mNeedUpdate = true;}
+   void finalPath(VPath& result);
+   void updatePath(const VPath &path) {mTemp = path; mDirtyPath = true;}
    bool staticPath() const { return mStaticPath; }
    void setParent(LOTContentGroupItem *parent) {mParent = parent;}
    LOTContentGroupItem *parent() const {return mParent;}
@@ -377,10 +377,8 @@ private:
    LOTContentGroupItem                    *mParent{nullptr};
    VPath                                   mLocalPath;
    VPath                                   mTemp;
-   VPath                                   mFinalPath;
    int                                     mFrameNo{-1};
-   bool                                    mPathChanged{true};
-   bool                                    mNeedUpdate{true};
+   bool                                    mDirtyPath{true};
    bool                                    mStaticPath;
 };
 
index 475e144..c257dd2 100644 (file)
@@ -676,7 +676,7 @@ void VPath::VPathData::addPolygon(float points, float radius, float roundness,
     close();
 }
 
-void VPath::VPathData::addPath(const VPathData &path)
+void VPath::VPathData::addPath(const VPathData &path, const VMatrix *m)
 {
     size_t segment = path.segments();
 
@@ -687,8 +687,15 @@ void VPath::VPathData::addPath(const VPathData &path)
     if (m_elements.capacity() < m_elements.size() + path.m_elements.size())
         m_elements.reserve(m_elements.size() + path.m_elements.size());
 
-    std::copy(path.m_points.begin(), path.m_points.end(),
-              back_inserter(m_points));
+    if (m) {
+        for (const auto &i : path.m_points) {
+            m_points.push_back(m->map(i));
+        }
+    } else {
+        std::copy(path.m_points.begin(), path.m_points.end(),
+                  back_inserter(m_points));
+    }
+
     std::copy(path.m_elements.begin(), path.m_elements.end(),
               back_inserter(m_elements));
 
index 6045854..c540e77 100644 (file)
@@ -63,6 +63,7 @@ public:
                      float startAngle, float cx, float cy,
                      VPath::Direction dir = Direction::CW);
     void addPath(const VPath &path);
+    void  addPath(const VPath &path, const VMatrix &m);
     void  transform(const VMatrix &m);
     float length() const;
     const std::vector<VPath::Element> &elements() const;
@@ -98,7 +99,7 @@ private:
         void  addPolygon(float points, float radius, float roundness,
                          float startAngle, float cx, float cy,
                          VPath::Direction dir = Direction::CW);
-        void  addPath(const VPathData &path);
+        void  addPath(const VPathData &path, const VMatrix *m = nullptr);
         void  clone(const VPath::VPathData &o) { *this = o;}
         const std::vector<VPath::Element> &elements() const
         {
@@ -253,6 +254,13 @@ inline void VPath::addPath(const VPath &path)
     }
 }
 
+inline void  VPath::addPath(const VPath &path, const VMatrix &m)
+{
+    if (path.empty()) return;
+
+    d.write().addPath(path.d.read(), &m);
+}
+
 inline const std::vector<VPath::Element> &VPath::elements() const
 {
     return d->elements();