vdasher: refactor dash property parsing and handling.
authorsubhransu mohanty <sub.mohanty@samsung.com>
Wed, 31 Jul 2019 08:06:17 +0000 (17:06 +0900)
committerHermet Park <hermetpark@gmail.com>
Mon, 12 Aug 2019 08:30:34 +0000 (17:30 +0900)
- reduce Stroke and GStroke model object size by keeping a vector instead of fixed array property.
- keep a vector instead of fixed size array in model.
- keep a vector instead of fix size array in shadow tree.
- refactor getDashInfo() to DashProperty class and reuse by both Stroke and GradientStroke model object.
- enable move constructor in LOTAnimatable class to support creation vector of objects.

src/lottie/lottieitem.cpp
src/lottie/lottieitem.h
src/lottie/lottiemodel.cpp
src/lottie/lottiemodel.h
src/lottie/lottieparser.cpp
src/lottie/lottieproxymodel.h
src/vector/vdasher.cpp
src/vector/vdrawable.cpp
src/vector/vdrawable.h

index 0617368..0545df9 100644 (file)
@@ -1362,18 +1362,13 @@ void LOTGFillItem::updateRenderNode()
 }
 
 LOTStrokeItem::LOTStrokeItem(LOTStrokeData *data)
-    : LOTPaintDataItem(data->isStatic()), mModel(data)
-{
-    mDashArraySize = 0;
-}
+    : LOTPaintDataItem(data->isStatic()), mModel(data){}
 
 void LOTStrokeItem::updateContent(int frameNo)
 {
     mColor = mModel.color(frameNo).toColor(mModel.opacity(frameNo));
     mWidth = mModel.strokeWidth(frameNo);
-    if (mModel.hasDashInfo()) {
-        mDashArraySize = mModel.getDashInfo(frameNo, mDashArray);
-    }
+    if (mModel.hasDashInfo()) mModel.getDashInfo(frameNo, mDashInfo);
 }
 
 static float getScale(const VMatrix &matrix)
@@ -1399,21 +1394,15 @@ void LOTStrokeItem::updateRenderNode()
         getScale(static_cast<LOTContentGroupItem *>(parent())->matrix());
     mDrawable.setStrokeInfo(mModel.capStyle(), mModel.joinStyle(),
                             mModel.meterLimit(), mWidth * scale);
-    if (mDashArraySize) {
-        for (int i = 0; i < mDashArraySize; i++) mDashArray[i] *= scale;
-
-        /* AE draw the dash even if dash value is 0 */
-        if (vCompare(mDashArray[0], 0.0f)) mDashArray[0] = 0.1f;
 
-        mDrawable.setDashInfo(mDashArray, mDashArraySize);
+    if (!mDashInfo.empty()) {
+        for (auto &elm : mDashInfo) elm *= scale;
+        mDrawable.setDashInfo(mDashInfo);
     }
 }
 
 LOTGStrokeItem::LOTGStrokeItem(LOTGStrokeData *data)
-    : LOTPaintDataItem(data->isStatic()), mData(data)
-{
-    mDashArraySize = 0;
-}
+    : LOTPaintDataItem(data->isStatic()), mData(data){}
 
 void LOTGStrokeItem::updateContent(int frameNo)
 {
@@ -1424,9 +1413,8 @@ void LOTGStrokeItem::updateContent(int frameNo)
     mJoin = mData->joinStyle();
     mMiterLimit = mData->meterLimit();
     mWidth = mData->width(frameNo);
-    if (mData->hasDashInfo()) {
-        mDashArraySize = mData->getDashInfo(frameNo, mDashArray);
-    }
+
+    if (mData->hasDashInfo()) mData->getDashInfo(frameNo, mDashInfo);
 }
 
 void LOTGStrokeItem::updateRenderNode()
@@ -1435,9 +1423,10 @@ void LOTGStrokeItem::updateRenderNode()
     mGradient->setAlpha(mAlpha * parentAlpha());
     mDrawable.setBrush(VBrush(mGradient.get()));
     mDrawable.setStrokeInfo(mCap, mJoin, mMiterLimit, mWidth * scale);
-    if (mDashArraySize) {
-        for (int i = 0; i < mDashArraySize; i++) mDashArray[i] *= scale;
-        mDrawable.setDashInfo(mDashArray, mDashArraySize);
+
+    if (!mDashInfo.empty()) {
+        for (auto &elm : mDashInfo) elm *= scale;
+        mDrawable.setDashInfo(mDashInfo);
     }
 }
 
@@ -1628,7 +1617,7 @@ void LOTDrawable::sync()
     if (mFlag & DirtyState::None) return;
 
     if (mFlag & DirtyState::Path) {
-        if (mStroke.mDash.size()) {
+        if (!mStroke.mDash.empty()) {
             VDasher dasher(mStroke.mDash.data(), mStroke.mDash.size());
             mPath = dasher.dashed(mPath);
         }
index 9d7ccea..b3165ef 100644 (file)
@@ -454,8 +454,7 @@ private:
    LOTProxyModel<LOTStrokeData> mModel;
    VColor                       mColor;
    float                        mWidth{0};
-   float                        mDashArray[6];
-   int                          mDashArraySize{0};
+   std::vector<float>           mDashInfo;
 };
 
 class LOTGStrokeItem : public LOTPaintDataItem
@@ -474,8 +473,7 @@ private:
    VColor                        mColor;
    float                         mAlpha{1.0};
    float                         mWidth{0};
-   float                         mDashArray[6];
-   int                           mDashArraySize{0};
+   std::vector<float>            mDashInfo;
 };
 
 
index 87c27e2..4c6b7e3 100644 (file)
@@ -135,43 +135,27 @@ VMatrix TransformData::matrix(int frameNo, bool autoOrient) const
     return m;
 }
 
-int LOTStrokeData::getDashInfo(int frameNo, float *array) const
+void LOTDashProperty::getDashInfo(int frameNo, std::vector<float>& result) const
 {
-    if (!mDash.mDashCount) return 0;
-    // odd case
-    if (mDash.mDashCount % 2) {
-        for (int i = 0; i < mDash.mDashCount; i++) {
-            array[i] = mDash.mDashArray[i].value(frameNo);
-        }
-        return mDash.mDashCount;
-    } else {  // even case when last gap info is not provided.
-        int i;
-        for (i = 0; i < mDash.mDashCount - 1; i++) {
-            array[i] = mDash.mDashArray[i].value(frameNo);
-        }
-        array[i] = array[i - 1];
-        array[i + 1] = mDash.mDashArray[i].value(frameNo);
-        return mDash.mDashCount + 1;
-    }
-}
+    result.clear();
 
-int LOTGStrokeData::getDashInfo(int frameNo, float *array) const
-{
-    if (!mDash.mDashCount) return 0;
-    // odd case
-    if (mDash.mDashCount % 2) {
-        for (int i = 0; i < mDash.mDashCount; i++) {
-            array[i] = mDash.mDashArray[i].value(frameNo);
-        }
-        return mDash.mDashCount;
-    } else {  // even case when last gap info is not provided.
-        int i;
-        for (i = 0; i < mDash.mDashCount - 1; i++) {
-            array[i] = mDash.mDashArray[i].value(frameNo);
-        }
-        array[i] = array[i - 1];
-        array[i + 1] = mDash.mDashArray[i].value(frameNo);
-        return mDash.mDashCount + 1;
+    if (mData.empty()) return;
+
+    if (result.capacity() < mData.size()) result.reserve(mData.size() + 1);
+
+    for (const auto &elm : mData)
+        result.push_back(elm.value(frameNo));
+
+    // if the size is even then we are missing last
+    // gap information which is same as the last dash value
+    // copy it from the last dash value.
+    // NOTE: last value is the offset and last-1 is the last dash value.
+    auto size = result.size();
+    if ((size % 2) == 0) {
+        //copy offset value to end.
+        result.push_back(result.back());
+        // copy dash value to gap.
+        result[size-1] = result[size-2];
     }
 }
 
index 2cc7e83..550a003 100644 (file)
@@ -287,9 +287,17 @@ public:
         return impl.mValue;
     }
 
+    LOTAnimatable(LOTAnimatable &&other) noexcept {
+        if (!other.mStatic) {
+            construct(impl.mAnimInfo, std::move(other.impl.mAnimInfo));
+            mStatic = false;
+        } else {
+            construct(impl.mValue, std::move(other.impl.mValue));
+            mStatic = true;
+        }
+    }
     // delete special member functions
     LOTAnimatable(const LOTAnimatable &) = delete;
-    LOTAnimatable(LOTAnimatable &&) = delete;
     LOTAnimatable& operator=(const LOTAnimatable&) = delete;
     LOTAnimatable& operator=(LOTAnimatable&&) = delete;
 
@@ -642,9 +650,15 @@ public:
 
 struct LOTDashProperty
 {
-    LOTAnimatable<float>     mDashArray[5]; /* "d" "g" "o"*/
-    int                      mDashCount{0};
-    bool                     mStatic{true};
+    std::vector<LOTAnimatable<float>> mData;
+    bool empty() const {return mData.empty();}
+    size_t size() const {return mData.size();}
+    bool isStatic() const {
+        for(const auto &elm : mData)
+            if (!elm.isStatic()) return false;
+        return true;
+    }
+    void getDashInfo(int frameNo, std::vector<float>& result) const;
 };
 
 class LOTStrokeData : public LOTData
@@ -657,8 +671,11 @@ public:
     CapStyle capStyle() const {return mCapStyle;}
     JoinStyle joinStyle() const {return mJoinStyle;}
     float meterLimit() const{return mMeterLimit;}
-    bool hasDashInfo() const { return !(mDash.mDashCount == 0);}
-    int getDashInfo(int frameNo, float *array) const;
+    bool  hasDashInfo() const {return !mDash.empty();}
+    void getDashInfo(int frameNo, std::vector<float>& result) const
+    {
+        return mDash.getDashInfo(frameNo, result);
+    }
 public:
     LOTAnimatable<LottieColor>        mColor;      /* "c" */
     LOTAnimatable<float>              mOpacity{100};    /* "o" */
@@ -764,8 +781,11 @@ public:
     CapStyle capStyle() const {return mCapStyle;}
     JoinStyle joinStyle() const {return mJoinStyle;}
     float meterLimit() const{return mMeterLimit;}
-    bool hasDashInfo() const { return !(mDash.mDashCount == 0);}
-    int getDashInfo(int frameNo, float *array) const;
+    bool  hasDashInfo() const {return !mDash.empty();}
+    void getDashInfo(int frameNo, std::vector<float>& result) const
+    {
+        return mDash.getDashInfo(frameNo, result);
+    }
 public:
     LOTAnimatable<float>           mWidth;       /* "w" */
     CapStyle                       mCapStyle{CapStyle::Flat};    /* "lc" */
index c0f1738..3d84a4f 100644 (file)
@@ -1567,7 +1567,7 @@ std::shared_ptr<LOTData> LottieParserImpl::parseStrokeObject()
         }
     }
     obj->setStatic(obj->mColor.isStatic() && obj->mOpacity.isStatic() &&
-                   obj->mWidth.isStatic() && obj->mDash.mStatic);
+                   obj->mWidth.isStatic() && obj->mDash.isStatic());
     return sharedStroke;
 }
 
@@ -1634,8 +1634,6 @@ std::shared_ptr<LOTData> LottieParserImpl::parseGFillObject()
 
 void LottieParserImpl::parseDashProperty(LOTDashProperty &dash)
 {
-    dash.mDashCount = 0;
-    dash.mStatic = true;
     RAPIDJSON_ASSERT(PeekType() == kArrayType);
     EnterArray();
     while (NextArrayValue()) {
@@ -1643,20 +1641,13 @@ void LottieParserImpl::parseDashProperty(LOTDashProperty &dash)
         EnterObject();
         while (const char *key = NextObjectKey()) {
             if (0 == strcmp(key, "v")) {
-                parseProperty(dash.mDashArray[dash.mDashCount++]);
+                dash.mData.emplace_back();
+                parseProperty(dash.mData.back());
             } else {
                 Skip(key);
             }
         }
     }
-
-    // update the staic proprty
-    for (int i = 0; i < dash.mDashCount; i++) {
-        if (!dash.mDashArray[i].isStatic()) {
-            dash.mStatic = false;
-            break;
-        }
-    }
 }
 
 /*
@@ -1688,7 +1679,7 @@ std::shared_ptr<LOTData> LottieParserImpl::parseGStrokeObject()
     }
 
     obj->setStatic(obj->isStatic() && obj->mWidth.isStatic() &&
-                   obj->mDash.mStatic);
+                   obj->mDash.isStatic());
     return sharedGStroke;
 }
 
index 8b5ad17..82be2ed 100644 (file)
@@ -298,7 +298,9 @@ public:
     CapStyle capStyle() const {return _modelData->capStyle();}
     JoinStyle joinStyle() const {return _modelData->joinStyle();}
     bool hasDashInfo() const { return _modelData->hasDashInfo();}
-    int getDashInfo(int frameNo, float *array) const {return _modelData->getDashInfo(frameNo, array);}
+    void getDashInfo(int frameNo, std::vector<float>& result) const {
+        return _modelData->getDashInfo(frameNo, result);
+    }
 
 private:
     T                         *_modelData;
index dfd0835..e83728f 100644 (file)
@@ -187,7 +187,10 @@ void VDasher::cubicTo(const VPointF &cp1, const VPointF &cp2, const VPointF &e)
 
 VPath VDasher::dashed(const VPath &path)
 {
+    if (mNoLength && mNoGap) return path;
+
     if (path.empty() || mNoLength) return VPath();
+
     if (mNoGap) return path;
 
     mResult = {};
index af44032..4ffecfe 100644 (file)
@@ -59,13 +59,13 @@ void VDrawable::setStrokeInfo(CapStyle cap, JoinStyle join, float meterLimit,
     mFlag |= DirtyState::Path;
 }
 
-void VDrawable::setDashInfo(float *array, uint size)
+void VDrawable::setDashInfo(std::vector<float> &dashInfo)
 {
     bool hasChanged = false;
 
-    if (mStroke.mDash.size() == size) {
-        for (uint i = 0; i < size; i++) {
-            if (!vCompare(mStroke.mDash[i], array[i])) {
+    if (mStroke.mDash.size() == dashInfo.size()) {
+        for (uint i = 0; i < dashInfo.size(); i++) {
+            if (!vCompare(mStroke.mDash[i], dashInfo[i])) {
                 hasChanged = true;
                 break;
             }
@@ -76,11 +76,8 @@ void VDrawable::setDashInfo(float *array, uint size)
 
     if (!hasChanged) return;
 
-    mStroke.mDash.clear();
+    mStroke.mDash = dashInfo;
 
-    for (uint i = 0; i < size; i++) {
-        mStroke.mDash.push_back(array[i]);
-    }
     mFlag |= DirtyState::Path;
 }
 
index 861d9be..4ff7869 100644 (file)
@@ -43,7 +43,7 @@ public:
     void setBrush(const VBrush &brush) { mBrush = brush; }
     void setStrokeInfo(CapStyle cap, JoinStyle join, float meterLimit,
                        float strokeWidth);
-    void setDashInfo(float *array, uint size);
+    void setDashInfo(std::vector<float> &dashInfo);
     void preprocess(const VRect &clip);
     VRle rle();