From cbf124632ff7e4c48cb464230865df8da37cd7e7 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 2 Jul 2024 18:14:00 +0900 Subject: [PATCH] lottie: allow image asset sharing among LottiePicture instances Previously, the Lottie builder didn't account for image asset sharing among multiple layers. This update rectifies the situation. issue: https://github.com/thorvg/thorvg/issues/2428 --- src/loaders/lottie/tvgLottieBuilder.cpp | 28 +++++++++---------------- src/loaders/lottie/tvgLottieModel.cpp | 5 ++--- src/loaders/lottie/tvgLottieModel.h | 4 ++-- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index 5271ab94..6ce4233f 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -1028,32 +1028,23 @@ static void _updateSolid(LottieLayer* layer) static void _updateImage(LottieGroup* layer) { auto image = static_cast(layer->children.first()); - auto picture = image->picture; - if (!picture) { - picture = Picture::gen().release(); + if (!image->picture) { + image->picture = Picture::gen().release(); //force to load a picture on the same thread TaskScheduler::async(false); - if (image->size > 0) { - if (picture->load((const char*)image->b64Data, image->size, image->mimeType) != Result::Success) { - delete(picture); - return; - } - } else { - if (picture->load(image->path) != Result::Success) { - delete(picture); - return; - } - } + if (image->size > 0) image->picture->load((const char*)image->b64Data, image->size, image->mimeType); + else image->picture->load(image->path); TaskScheduler::async(true); - image->picture = picture; - PP(picture)->ref(); + PP(image->picture)->ref(); } - layer->scene->push(cast(picture)); + + if (image->refCnt == 1) layer->scene->push(tvg::cast(image->picture)); + else layer->scene->push(tvg::cast(image->picture->duplicate())); } @@ -1190,7 +1181,7 @@ static bool _updateMatte(LottieLayer* root, LottieLayer* layer, float frameNo, L if (target->scene) { layer->scene->composite(cast(target->scene), layer->matteType); - } else if (layer->matteType == CompositeMethod::AlphaMask || layer->matteType == CompositeMethod::LumaMask) { + } else if (layer->matteType == CompositeMethod::AlphaMask || layer->matteType == CompositeMethod::LumaMask) { //matte target is not exist. alpha blending definitely bring an invisible result delete(layer->scene); layer->scene = nullptr; @@ -1272,6 +1263,7 @@ static void _buildReference(LottieComposition* comp, LottieLayer* layer) layer->reqFragment = assetLayer->reqFragment; } } else if (layer->type == LottieLayer::Image) { + ++static_cast(*asset)->refCnt; layer->children.push(*asset); } break; diff --git a/src/loaders/lottie/tvgLottieModel.cpp b/src/loaders/lottie/tvgLottieModel.cpp index 696c1b7e..e66f52d6 100644 --- a/src/loaders/lottie/tvgLottieModel.cpp +++ b/src/loaders/lottie/tvgLottieModel.cpp @@ -110,12 +110,11 @@ void LottieSlot::assign(LottieObject* target) LottieImage::~LottieImage() { - free(b64Data); - free(mimeType); - if (picture && PP(picture)->unref() == 0) { delete(picture); } + free(b64Data); + free(mimeType); } diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index 2ca9b2c7..9bfc5798 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -454,10 +454,10 @@ struct LottieImage : LottieObject char* b64Data = nullptr; char* path; }; + Picture* picture = nullptr; //tvg render data char* mimeType = nullptr; uint32_t size = 0; - - Picture* picture = nullptr; //tvg render data + uint16_t refCnt = 0; //refernce count ~LottieImage();