From 2b8ce3d6c348c4e4580bc92d14d9291c92dfb8eb Mon Sep 17 00:00:00 2001 From: subhransu mohanty Date: Mon, 3 Jun 2019 16:23:35 +0900 Subject: [PATCH] rlottie: Fix precomp layer rendering issue when it has alpha value 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 | 30 ++++++++++++++++++++++++++++-- src/lottie/lottieitem.h | 4 ++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/lottie/lottieitem.cpp b/src/lottie/lottieitem.cpp index 2ee9813344..2e2d6b11ba 100644 --- a/src/lottie/lottieitem.cpp +++ b/src/lottie/lottieitem.cpp @@ -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(i.get()); @@ -552,6 +553,8 @@ LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel) if (!layerModel->layerSize().empty()) { mClipper = std::make_unique(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); } } diff --git a/src/lottie/lottieitem.h b/src/lottie/lottieitem.h index 48c750175a..d5e8eee18a 100644 --- a/src/lottie/lottieitem.h +++ b/src/lottie/lottieitem.h @@ -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 &){} @@ -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: