lottie/opt: refactor drawable class to optimize object size
authorsubhransu mohanty <sub.mohanty@samsung.com>
Wed, 30 Oct 2019 09:18:10 +0000 (18:18 +0900)
committerJongmin Lee <jm105.lee@samsung.com>
Mon, 11 Nov 2019 20:58:15 +0000 (05:58 +0900)
src/lottie/lottieitem.cpp
src/lottie/lottieitem_capi.cpp
src/vector/vdrawable.cpp
src/vector/vdrawable.h

index 6372c59..93f7b77 100644 (file)
@@ -1234,7 +1234,14 @@ bool LOTGFillItem::updateContent(int frameNo, const VMatrix &matrix, float alpha
 }
 
 LOTStrokeItem::LOTStrokeItem(LOTStrokeData *data)
-    : LOTPaintDataItem(data->isStatic()), mModel(data){}
+    : LOTPaintDataItem(data->isStatic()), mModel(data)
+{
+    if (mModel.hasDashInfo()) {
+        mDrawable.setType(VDrawable::Type::StrokeWithDash);
+    } else {
+        mDrawable.setType(VDrawable::Type::Stroke);
+    }
+}
 
 static thread_local std::vector<float> Dash_Vector;
 
@@ -1264,7 +1271,14 @@ bool LOTStrokeItem::updateContent(int frameNo, const VMatrix &matrix, float alph
 }
 
 LOTGStrokeItem::LOTGStrokeItem(LOTGStrokeData *data)
-    : LOTPaintDataItem(data->isStatic()), mData(data){}
+    : LOTPaintDataItem(data->isStatic()), mData(data)
+{
+    if (mData->hasDashInfo()) {
+        mDrawable.setType(VDrawable::Type::StrokeWithDash);
+    } else {
+        mDrawable.setType(VDrawable::Type::Stroke);
+    }
+}
 
 bool LOTGStrokeItem::updateContent(int frameNo, const VMatrix &matrix, float alpha)
 {
index 6242f43..a6130d8 100644 (file)
@@ -234,10 +234,7 @@ void LOTDrawable::sync()
     if (mFlag & DirtyState::None) return;
 
     if (mFlag & DirtyState::Path) {
-        if (!mStroke.mDash.empty()) {
-            VDasher dasher(mStroke.mDash.data(), mStroke.mDash.size());
-            mPath = dasher.dashed(mPath);
-        }
+        applyDashOp();
         const std::vector<VPath::Element> &elm = mPath.elements();
         const std::vector<VPointF> &       pts = mPath.points();
         const float *ptPtr = reinterpret_cast<const float *>(pts.data());
@@ -249,12 +246,12 @@ void LOTDrawable::sync()
         mCNode->mFlag |= ChangeFlagPath;
     }
 
-    if (mStroke.enable) {
-        mCNode->mStroke.width = mStroke.width;
-        mCNode->mStroke.miterLimit = mStroke.miterLimit;
+    if (mStrokeInfo) {
+        mCNode->mStroke.width = mStrokeInfo->width;
+        mCNode->mStroke.miterLimit = mStrokeInfo->miterLimit;
         mCNode->mStroke.enable = 1;
 
-        switch (mStroke.cap) {
+        switch (mStrokeInfo->cap) {
         case CapStyle::Flat:
             mCNode->mStroke.cap = LOTCapStyle::CapFlat;
             break;
@@ -266,7 +263,7 @@ void LOTDrawable::sync()
             break;
         }
 
-        switch (mStroke.join) {
+        switch (mStrokeInfo->join) {
         case JoinStyle::Miter:
             mCNode->mStroke.join = LOTJoinStyle::JoinMiter;
             break;
index cba3288..7245d5f 100644 (file)
 #include "vdasher.h"
 #include "vraster.h"
 
+VDrawable::VDrawable(VDrawable::Type type)
+{
+    setType(type);
+}
+
+VDrawable::~VDrawable()
+{
+    if (mStrokeInfo) {
+        if (mType == Type::StrokeWithDash) {
+            delete static_cast<StrokeWithDashInfo *>(mStrokeInfo);
+        } else {
+            delete mStrokeInfo;
+        }
+    }
+}
+
+void VDrawable::setType(VDrawable::Type type)
+{
+    mType = type;
+    if (mType == VDrawable::Type::Stroke) {
+        mStrokeInfo = new StrokeInfo();
+    } else if (mType == VDrawable::Type::StrokeWithDash) {
+        mStrokeInfo = new StrokeWithDashInfo();
+    }
+}
+
+void VDrawable::applyDashOp()
+{
+    if (mStrokeInfo && (mType == Type::StrokeWithDash)) {
+        auto obj = static_cast<StrokeWithDashInfo *>(mStrokeInfo);
+        if (!obj->mDash.empty()) {
+            VDasher dasher(obj->mDash.data(), obj->mDash.size());
+            mPath.clone(dasher.dashed(mPath));
+        }
+    }
+}
+
 void VDrawable::preprocess(const VRect &clip)
 {
     if (mFlag & (DirtyState::Path)) {
-        if (mStroke.enable) {
-            if (mStroke.mDash.size()) {
-                VDasher dasher(mStroke.mDash.data(), mStroke.mDash.size());
-                mPath.clone(dasher.dashed(mPath));
-            }
-            mRasterizer.rasterize(std::move(mPath), mStroke.cap, mStroke.join,
-                                  mStroke.width, mStroke.miterLimit, clip);
-        } else {
+        if (mType == Type::Fill) {
             mRasterizer.rasterize(std::move(mPath), mFillRule, clip);
+        } else {
+            applyDashOp();
+            mRasterizer.rasterize(std::move(mPath), mStrokeInfo->cap, mStrokeInfo->join,
+                                  mStrokeInfo->width, mStrokeInfo->miterLimit, clip);
         }
         mPath = {};
         mFlag &= ~DirtyFlag(DirtyState::Path);
@@ -46,26 +80,30 @@ VRle VDrawable::rle()
 void VDrawable::setStrokeInfo(CapStyle cap, JoinStyle join, float miterLimit,
                               float strokeWidth)
 {
-    if ((mStroke.cap == cap) && (mStroke.join == join) &&
-        vCompare(mStroke.miterLimit, miterLimit) &&
-        vCompare(mStroke.width, strokeWidth))
+    assert(mStrokeInfo);
+    if ((mStrokeInfo->cap == cap) && (mStrokeInfo->join == join) &&
+        vCompare(mStrokeInfo->miterLimit, miterLimit) &&
+        vCompare(mStrokeInfo->width, strokeWidth))
         return;
 
-    mStroke.enable = true;
-    mStroke.cap = cap;
-    mStroke.join = join;
-    mStroke.miterLimit = miterLimit;
-    mStroke.width = strokeWidth;
+    mStrokeInfo->cap = cap;
+    mStrokeInfo->join = join;
+    mStrokeInfo->miterLimit = miterLimit;
+    mStrokeInfo->width = strokeWidth;
     mFlag |= DirtyState::Path;
 }
 
 void VDrawable::setDashInfo(std::vector<float> &dashInfo)
 {
+    assert(mStrokeInfo);
+    assert(mType == VDrawable::Type::StrokeWithDash);
+
+    auto obj = static_cast<StrokeWithDashInfo *>(mStrokeInfo);
     bool hasChanged = false;
 
-    if (mStroke.mDash.size() == dashInfo.size()) {
-        for (uint i = 0; i < dashInfo.size(); i++) {
-            if (!vCompare(mStroke.mDash[i], dashInfo[i])) {
+    if (obj->mDash.size() == dashInfo.size()) {
+        for (uint i = 0; i < dashInfo.size(); ++i) {
+            if (!vCompare(obj->mDash[i], dashInfo[i])) {
                 hasChanged = true;
                 break;
             }
@@ -76,7 +114,7 @@ void VDrawable::setDashInfo(std::vector<float> &dashInfo)
 
     if (!hasChanged) return;
 
-    mStroke.mDash = dashInfo;
+    obj->mDash = dashInfo;
 
     mFlag |= DirtyState::Path;
 }
index 749865d..05e5290 100644 (file)
@@ -1,16 +1,16 @@
-/* 
+/*
  * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 class VDrawable {
 public:
-    enum class DirtyState {
-        None = 0x00000000,
-        Path = 0x00000001,
-        Stroke = 0x00000010,
-        Brush = 0x00000100,
+    enum class DirtyState : unsigned char {
+        None = 1<<1,
+        Path = 1<<2,
+        Stroke = 1<<3,
+        Brush = 1<<4,
         All = (None | Path | Stroke | Brush)
     };
+
     enum class Type : unsigned char{
         Fill,
         Stroke,
+        StrokeWithDash
     };
+
+    explicit VDrawable(VDrawable::Type type = Type::Fill);
+    void setType(VDrawable::Type type);
+    ~VDrawable();
+
     typedef vFlag<DirtyState> DirtyFlag;
     void setPath(const VPath &path);
     void setFillRule(FillRule rule) { mFillRule = rule; }
@@ -45,24 +52,30 @@ public:
                        float strokeWidth);
     void setDashInfo(std::vector<float> &dashInfo);
     void preprocess(const VRect &clip);
+    void applyDashOp();
     VRle rle();
 
 public:
     struct StrokeInfo {
-        std::vector<float> mDash;
         float              width{0.0};
         float              miterLimit{10};
-        bool               enable{false};
         CapStyle           cap{CapStyle::Flat};
         JoinStyle          join{JoinStyle::Bevel};
     };
-    VRasterizer       mRasterizer;
-    VBrush            mBrush;
-    VPath             mPath;
-    StrokeInfo        mStroke;
-    DirtyFlag         mFlag{DirtyState::All};
-    FillRule          mFillRule{FillRule::Winding};
-    VDrawable::Type   mType{Type::Fill};
+
+    struct StrokeWithDashInfo : public StrokeInfo{
+        std::vector<float> mDash;
+    };
+
+public:
+    VPath                    mPath;
+    VBrush                   mBrush;
+    VRasterizer              mRasterizer;
+    StrokeInfo              *mStrokeInfo{nullptr};
+
+    DirtyFlag                mFlag{DirtyState::All};
+    FillRule                 mFillRule{FillRule::Winding};
+    VDrawable::Type          mType{Type::Fill};
 };
 
 #endif  // VDRAWABLE_H