rlottie: Fix precomp layer rendering issue when it has alpha value
authorsubhransu mohanty <sub.mohanty@samsung.com>
Mon, 3 Jun 2019 07:23:35 +0000 (16:23 +0900)
committerHermet Park <hermetpark@gmail.com>
Wed, 19 Jun 2019 04:35:17 +0000 (13:35 +0900)
When the precomp layer has alpha transparency and has more than 1 child layer and they overlap each other
if we just propagate the alpha to child layer it will be applied twice in overlapped area.
in this case we treat the precomp layer as complex content and don't propagate the alpha transparency.
instead we create a buffer and draw all the child layers and then we blend with the main buffer
with the alpha transparency value.

src/lottie/lottieitem.cpp
src/lottie/lottieitem.h

index 2ee9813344f05ef719bcf2c8bb571a227cdf7bac..2e2d6b11baa0217cedf4c809df39c245748d48df 100644 (file)
@@ -77,6 +77,7 @@ LOTCompItem::LOTCompItem(LOTModel *model)
 {
     mCompData = model->mRoot.get();
     mRootLayer = createLayerItem(mCompData->mRootLayer.get());
+    mRootLayer->setComplexContent(false);
     mViewSize = mCompData->size();
 }
 
@@ -526,7 +527,7 @@ bool LOTLayerItem::visible() const
 
 LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel)
     : LOTLayerItem(layerModel)
-{
+{   
     // 1. create layer item
     for (auto &i : mLayerData->mChildren) {
         LOTLayerData *layerModel = static_cast<LOTLayerData *>(i.get());
@@ -552,6 +553,8 @@ LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel)
     if (!layerModel->layerSize().empty()) {
         mClipper = std::make_unique<LOTClipperItem>(layerModel->layerSize());
     }
+
+    if (mLayers.size() > 1) setComplexContent(true);
 }
 
 void LOTCompLayerItem::buildLayerNode()
@@ -582,6 +585,27 @@ void LOTCompLayerItem::buildLayerNode()
 }
 
 void LOTCompLayerItem::render(VPainter *painter, const VRle &inheritMask, const VRle &matteRle)
+{
+    if (vIsZero(combinedAlpha())) return;
+
+    if (vCompare(combinedAlpha(), 1.0)) {
+        renderHelper(painter, inheritMask, matteRle);
+    } else {
+        if (complexContent()) {
+            VSize size = painter->clipBoundingRect().size();
+            VPainter srcPainter;
+            VBitmap srcBitmap(size.width(), size.height(), VBitmap::Format::ARGB32_Premultiplied);
+            srcPainter.begin(&srcBitmap);
+            renderHelper(&srcPainter, inheritMask, matteRle);
+            srcPainter.end();
+            painter->drawBitmap(VPoint(), srcBitmap, combinedAlpha() * 255);
+        } else {
+            renderHelper(painter, inheritMask, matteRle);
+        }
+    }
+}
+
+void LOTCompLayerItem::renderHelper(VPainter *painter, const VRle &inheritMask, const VRle &matteRle)
 {
     VRle mask;
     if (mLayerMask) {
@@ -702,8 +726,10 @@ void LOTCompLayerItem::updateContent()
         mClipper->update(combinedMatrix());
     }
     int mappedFrame = mLayerData->timeRemap(frameNo());
+    float alpha = combinedAlpha();
+    if (complexContent()) alpha = 1;
     for (const auto &layer : mLayers) {
-        layer->update( mappedFrame, combinedMatrix(), combinedAlpha());
+        layer->update( mappedFrame, combinedMatrix(), alpha);
     }
 }
 
index 48c750175a974bc43fd8319e4c76ba6b0da94e67..d5e8eee18afc49e7b7302c9b8382773ab8c69956 100644 (file)
@@ -95,6 +95,8 @@ public:
    int id() const {return mLayerData->id();}
    int parentId() const {return mLayerData->parentId();}
    void setParentLayer(LOTLayerItem *parent){mParentLayer = parent;}
+   void setComplexContent(bool value) { mComplexContent = value;}
+   bool complexContent() const {return mComplexContent;}
    virtual void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha);
    VMatrix matrix(int frameNo) const;
    virtual void renderList(std::vector<VDrawable *> &){}
@@ -125,6 +127,7 @@ protected:
    float                                       mCombinedAlpha{0.0};
    int                                         mFrameNo{-1};
    DirtyFlag                                   mDirtyFlag{DirtyFlagBit::All};
+   bool                                        mComplexContent{false};
 };
 
 class LOTCompLayerItem: public LOTLayerItem
@@ -138,6 +141,7 @@ public:
 protected:
    void updateContent() final;
 private:
+    void renderHelper(VPainter *painter, const VRle &mask, const VRle &matteRle);
     void renderMatteLayer(VPainter *painter, const VRle &inheritMask, const VRle &matteRle,
                           LOTLayerItem *layer, LOTLayerItem *src);
 private: