From 40647d58821617501fe72c0840bb52551536ee8b Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 28 Mar 2024 12:03:29 +0900 Subject: [PATCH] lottie: optimize the rendering by preventing partial rendering branches. this optimization is to figure out if this group is a simple path drawing. In that case, the rendering context can be sharable with the parent's. --- src/loaders/lottie/tvgLottieModel.cpp | 13 ++++++++++--- src/loaders/lottie/tvgLottieModel.h | 24 ++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/loaders/lottie/tvgLottieModel.cpp b/src/loaders/lottie/tvgLottieModel.cpp index 8046e047..c8ce3dda 100644 --- a/src/loaders/lottie/tvgLottieModel.cpp +++ b/src/loaders/lottie/tvgLottieModel.cpp @@ -142,13 +142,20 @@ void LottieGroup::prepare(LottieObject::Type type) size_t fillCnt = 0; for (auto c = children.end() - 1; c >= children.begin(); --c) { - if (reqFragment) break; + if (!mergeable && reqFragment) break; + auto child = static_cast(*c); + + /* Figure out if this group is a simple path drawing. + In that case, the rendering context can be sharable with the parent's. */ + if (mergeable && !child->mergeable()) mergeable = false; + + if (reqFragment) continue; + /* Figure out if the rendering context should be fragmented. Multiple stroking or grouping with a stroking would occur this. This fragment resolves the overlapped stroke outlines. */ - if (reqFragment) continue; - if (child->type == LottieObject::Group) { + if (child->type == LottieObject::Group && !static_cast(child)->mergeable) { if (strokeCnt > 0 || fillCnt > 0) reqFragment = true; } else if (child->type == LottieObject::SolidStroke || child->type == LottieObject::GradientStroke) { if (strokeCnt > 0) reqFragment = true; diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index 65aced12..e10c9c67 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -124,6 +124,8 @@ struct LottieObject TVGERR("LOTTIE", "Unsupported slot type"); } + virtual bool mergeable() { return false; } + char* name = nullptr; Type type; bool hidden = false; //remove? @@ -195,17 +197,23 @@ struct LottieText : LottieObject struct LottieTrimpath : LottieObject { - enum Type : uint8_t { Individual = 1, Simultaneous = 2 }; + enum Type : uint8_t { Simultaneous = 1, Individual = 2 }; void prepare() { LottieObject::type = LottieObject::Trimpath; } + bool mergeable() override + { + if (!start.frames && start.value == 0.0f && !end.frames && end.value == 100.0f && !offset.frames && offset.value == 0.0f) return true; + return false; + } + void segment(float frameNo, float& start, float& end); LottieFloat start = 0.0f; - LottieFloat end = 0.0f; + LottieFloat end = 100.0f; LottieFloat offset = 0.0f; Type type = Simultaneous; }; @@ -215,6 +223,11 @@ struct LottieShape : LottieObject { virtual ~LottieShape() {} uint8_t direction = 0; //0: clockwise, 2: counter-clockwise, 3: xor(?) + + bool mergeable() override + { + return true; + } }; @@ -309,6 +322,12 @@ struct LottieTransform : LottieObject LottieObject::type = LottieObject::Transform; } + bool mergeable() override + { + if (!opacity.frames && opacity.value == 255) return true; + return false; + } + LottiePosition position = Point{0.0f, 0.0f}; LottieFloat rotation = 0.0f; //z rotation LottiePoint scale = Point{100.0f, 100.0f}; @@ -559,6 +578,7 @@ struct LottieGroup : LottieObject bool reqFragment = false; //requirment to fragment the render context bool buildDone = false; //completed in building the composition. + bool mergeable = true; //if this group is consisted of simple (transformed) shapes. };