From e69cc2b9360a2b99f7a45a90ac1893afba657260 Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Mon, 27 May 2024 21:59:15 +0200 Subject: [PATCH] lottie: add 'tp' tag support So far it hasn't been possible to specify a matte layer - by default, it was the layer above the calling layer. The 'tp' tag support has been introduced, enabling referencing any layer by its index. In cases where the layer referencing the matte was the first one, a segmentation fault was observed. This issue has now been resolved. @Issue: https://github.com/thorvg/thorvg/issues/2325 --- src/loaders/lottie/tvgLottieBuilder.cpp | 17 ++++++++++++++++- src/loaders/lottie/tvgLottieModel.cpp | 2 +- src/loaders/lottie/tvgLottieModel.h | 1 + src/loaders/lottie/tvgLottieParser.cpp | 17 +++-------------- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index 9178166b..fe774ba9 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -1319,6 +1319,20 @@ static bool _buildComposition(LottieComposition* comp, LottieGroup* parent) //attach the precomp layer. if (child->refId) _buildReference(comp, child); + if (child->matte.type != CompositeMethod::None) { + //no index of the matte layer is provided: the layer above is used as the matte source + if (child->mid == -1) { + if (c > parent->children.begin()) { + child->matte.target = static_cast(*(c - 1)); + } + //matte layer is specified by an index. + } else { + if (auto matte = comp->layer(child->mid)) { + child->matte.target = matte; + } + } + } + if (child->matte.target) { //parenting _bulidHierarchy(parent, child->matte.target); @@ -1353,7 +1367,8 @@ bool LottieBuilder::update(LottieComposition* comp, float frameNo) if (exps && comp->expressions) exps->update(comp->timeAtFrame(frameNo)); for (auto child = root->children.end() - 1; child >= root->children.begin(); --child) { - _updateLayer(root, static_cast(*child), frameNo, exps); + auto layer = static_cast(*child); + if (!layer->matteSrc) _updateLayer(root, layer, frameNo, exps); } return true; diff --git a/src/loaders/lottie/tvgLottieModel.cpp b/src/loaders/lottie/tvgLottieModel.cpp index 7fab8ffb..a1dd4e4c 100644 --- a/src/loaders/lottie/tvgLottieModel.cpp +++ b/src/loaders/lottie/tvgLottieModel.cpp @@ -354,7 +354,7 @@ LottieLayer::~LottieLayer() delete(*m); } - delete(matte.target); + matte.target = nullptr; delete(transform); } diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index eef6025d..1ce9806b 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -561,6 +561,7 @@ struct LottieLayer : LottieGroup float outFrame = 0.0f; float startFrame = 0.0f; char* refId = nullptr; //pre-composition reference. + int16_t mid = -1; //id of the matte layer. int16_t pid = -1; //id of the parent layer. int16_t id = -1; //id of the current layer. diff --git a/src/loaders/lottie/tvgLottieParser.cpp b/src/loaders/lottie/tvgLottieParser.cpp index 9d4dcbb8..7d5c88af 100644 --- a/src/loaders/lottie/tvgLottieParser.cpp +++ b/src/loaders/lottie/tvgLottieParser.cpp @@ -1229,6 +1229,7 @@ LottieLayer* LottieParser::parseLayer() else if (KEY_AS("h") || KEY_AS("sh")) getLayerSize(layer->h); else if (KEY_AS("sc")) layer->color = getColor(getString()); else if (KEY_AS("tt")) layer->matte.type = getMatteType(); + else if (KEY_AS("tp")) layer->mid = getInt(); else if (KEY_AS("masksProperties")) parseMasks(layer); else if (KEY_AS("hd")) layer->hidden = getBool(); else if (KEY_AS("refId")) layer->refId = getStringCopy(); @@ -1264,21 +1265,9 @@ LottieLayer* LottieParser::parseLayers() enterArray(); while (nextArrayValue()) { - if (auto layer = parseLayer()) { - if (layer->matte.type == CompositeMethod::None) { - root->children.push(layer); - } else { - //matte source must be located in the right previous. - auto matte = static_cast(root->children.last()); - if (matte->matteSrc) { - layer->matte.target = matte; - } else { - TVGLOG("LOTTIE", "Matte Source(%s) is not designated?", matte->name); - } - root->children.last() = layer; - } - } + if (auto layer = parseLayer()) root->children.push(layer); } + root->prepare(); return root; }