diff --git a/src/lottie/lottieitem.cpp b/src/lottie/lottieitem.cpp index 9f206841c6..25056cf4b3 100644 --- a/src/lottie/lottieitem.cpp +++ b/src/lottie/lottieitem.cpp @@ -119,7 +119,7 @@ bool LOTCompItem::render(const LOTBuffer &buffer) VPainter painter(&bitmap); VRle mask; - mRootLayer->render(&painter, mask); + mRootLayer->render(&painter, mask, nullptr); return true; } @@ -156,8 +156,16 @@ VRle LOTMaskItem::rle() return mRle; } -void LOTLayerItem::render(VPainter *painter, const VRle &inheritMask) +void LOTLayerItem::render(VPainter *painter, const VRle &inheritMask, LOTLayerItem *matteSource) { + VRle matteRle; + if (matteSource) { + std::vector matteList; + matteSource->renderList(matteList); + for (auto &i : matteList) { + matteRle = matteRle + i->rle(); + } + } std::vector list; renderList(list); VRle mask = inheritMask; @@ -170,12 +178,17 @@ void LOTLayerItem::render(VPainter *painter, const VRle &inheritMask) for (auto &i : list) { painter->setBrush(i->mBrush); - if (!mask.isEmpty()) { - VRle rle = i->rle() & mask; - painter->drawRle(VPoint(), rle); - } else { - painter->drawRle(VPoint(), i->rle()); + VRle rle = i->rle(); + if (!mask.isEmpty()) rle = i->rle() & mask; + + if (!matteRle.isEmpty()) { + if (mLayerData->mMatteType == MatteType::AlphaInv) { + rle = rle - matteRle; + } else { + rle = rle & matteRle; + } } + painter->drawRle(VPoint(), rle); } } @@ -326,8 +339,17 @@ void LOTCompLayerItem::updateStaticProperty() } } -void LOTCompLayerItem::render(VPainter *painter, const VRle &inheritMask) +void LOTCompLayerItem::render(VPainter *painter, const VRle &inheritMask, LOTLayerItem *matteSource) { + VRle matteRle; + if (matteSource) { + std::vector matteList; + matteSource->renderList(matteList); + for (auto &i : matteList) { + matteRle = matteRle + i->rle(); + } + } + VRle mask = inheritMask; if (hasMask()) { @@ -337,9 +359,21 @@ void LOTCompLayerItem::render(VPainter *painter, const VRle &inheritMask) mask = mask & inheritMask; } + LOTLayerItem *matteLayer = nullptr; for (auto i = mLayers.rbegin(); i != mLayers.rend(); ++i) { LOTLayerItem *layer = *i; - layer->render(painter, mask); + + if (!matteLayer && layer->hasMatte()) { + matteLayer = layer; + continue; + } + + if (matteLayer) { + matteLayer->render(painter, mask, layer); + matteLayer = nullptr; + } else { + layer->render(painter, mask, nullptr); + } } } diff --git a/src/lottie/lottieitem.h b/src/lottie/lottieitem.h index 42721ce6f0..6c769e02b3 100644 --- a/src/lottie/lottieitem.h +++ b/src/lottie/lottieitem.h @@ -64,7 +64,9 @@ public: VMatrix matrix(int frameNo) const; virtual void renderList(std::vector &list){} virtual void updateStaticProperty(); - virtual void render(VPainter *painter, const VRle &mask); + virtual void render(VPainter *painter, const VRle &mask, LOTLayerItem *matteSource); + bool hasMatte() { if (mLayerData->mMatteType == MatteType::None) return false; return true; } + protected: virtual void updateContent() = 0; inline VMatrix combinedMatrix() const {return mCombinedMatrix;} @@ -96,7 +98,7 @@ public: LOTCompLayerItem(LOTLayerData *layerData); void renderList(std::vector &list)final; void updateStaticProperty() final; - void render(VPainter *painter, const VRle &mask) final; + void render(VPainter *painter, const VRle &mask, LOTLayerItem *matteSource) final; protected: void updateContent() final; private: