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.
This commit is contained in:
subhransu mohanty 2019-06-03 16:23:35 +09:00 committed by Subhransu
parent 574122b5a4
commit 2b8ce3d6c3
2 changed files with 32 additions and 2 deletions

View File

@ -77,6 +77,7 @@ LOTCompItem::LOTCompItem(LOTModel *model)
{ {
mCompData = model->mRoot.get(); mCompData = model->mRoot.get();
mRootLayer = createLayerItem(mCompData->mRootLayer.get()); mRootLayer = createLayerItem(mCompData->mRootLayer.get());
mRootLayer->setComplexContent(false);
mViewSize = mCompData->size(); mViewSize = mCompData->size();
} }
@ -526,7 +527,7 @@ bool LOTLayerItem::visible() const
LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel) LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel)
: LOTLayerItem(layerModel) : LOTLayerItem(layerModel)
{ {
// 1. create layer item // 1. create layer item
for (auto &i : mLayerData->mChildren) { for (auto &i : mLayerData->mChildren) {
LOTLayerData *layerModel = static_cast<LOTLayerData *>(i.get()); LOTLayerData *layerModel = static_cast<LOTLayerData *>(i.get());
@ -552,6 +553,8 @@ LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel)
if (!layerModel->layerSize().empty()) { if (!layerModel->layerSize().empty()) {
mClipper = std::make_unique<LOTClipperItem>(layerModel->layerSize()); mClipper = std::make_unique<LOTClipperItem>(layerModel->layerSize());
} }
if (mLayers.size() > 1) setComplexContent(true);
} }
void LOTCompLayerItem::buildLayerNode() void LOTCompLayerItem::buildLayerNode()
@ -582,6 +585,27 @@ void LOTCompLayerItem::buildLayerNode()
} }
void LOTCompLayerItem::render(VPainter *painter, const VRle &inheritMask, const VRle &matteRle) 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; VRle mask;
if (mLayerMask) { if (mLayerMask) {
@ -702,8 +726,10 @@ void LOTCompLayerItem::updateContent()
mClipper->update(combinedMatrix()); mClipper->update(combinedMatrix());
} }
int mappedFrame = mLayerData->timeRemap(frameNo()); int mappedFrame = mLayerData->timeRemap(frameNo());
float alpha = combinedAlpha();
if (complexContent()) alpha = 1;
for (const auto &layer : mLayers) { for (const auto &layer : mLayers) {
layer->update( mappedFrame, combinedMatrix(), combinedAlpha()); layer->update( mappedFrame, combinedMatrix(), alpha);
} }
} }

View File

@ -95,6 +95,8 @@ public:
int id() const {return mLayerData->id();} int id() const {return mLayerData->id();}
int parentId() const {return mLayerData->parentId();} int parentId() const {return mLayerData->parentId();}
void setParentLayer(LOTLayerItem *parent){mParentLayer = parent;} 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); virtual void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha);
VMatrix matrix(int frameNo) const; VMatrix matrix(int frameNo) const;
virtual void renderList(std::vector<VDrawable *> &){} virtual void renderList(std::vector<VDrawable *> &){}
@ -125,6 +127,7 @@ protected:
float mCombinedAlpha{0.0}; float mCombinedAlpha{0.0};
int mFrameNo{-1}; int mFrameNo{-1};
DirtyFlag mDirtyFlag{DirtyFlagBit::All}; DirtyFlag mDirtyFlag{DirtyFlagBit::All};
bool mComplexContent{false};
}; };
class LOTCompLayerItem: public LOTLayerItem class LOTCompLayerItem: public LOTLayerItem
@ -138,6 +141,7 @@ public:
protected: protected:
void updateContent() final; void updateContent() final;
private: private:
void renderHelper(VPainter *painter, const VRle &mask, const VRle &matteRle);
void renderMatteLayer(VPainter *painter, const VRle &inheritMask, const VRle &matteRle, void renderMatteLayer(VPainter *painter, const VRle &inheritMask, const VRle &matteRle,
LOTLayerItem *layer, LOTLayerItem *src); LOTLayerItem *layer, LOTLayerItem *src);
private: private: