From 3b2c040f70142a3f154889b1a72c9b346ed2b0f8 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 15 Aug 2023 11:23:11 +0900 Subject: [PATCH] loader/lottie: add the missing solid color layer. --- src/loaders/lottie/tvgLottieBuilder.cpp | 12 +++++++++++- src/loaders/lottie/tvgLottieLoader.cpp | 6 +++++- src/loaders/lottie/tvgLottieLoader.h | 1 - src/loaders/lottie/tvgLottieModel.h | 2 +- src/loaders/lottie/tvgLottieParser.cpp | 24 +++++++++++++++--------- src/loaders/lottie/tvgLottieParser.h | 1 + 6 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index 5c224bda..ae73ae29 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -43,6 +43,7 @@ static bool _invisible(LottieGroup* group, int32_t frameNo) else return false; } + static bool _invisible(LottieLayer* layer, int32_t frameNo) { if (frameNo < layer->inFrame || frameNo > layer->outFrame) { @@ -349,6 +350,15 @@ static void _updatePrecomp(LottieLayer* precomp, int32_t frameNo, bool reset) } +static void _updateSolid(LottieLayer* layer, int32_t frameNo) +{ + auto shape = Shape::gen(); + shape->appendRect(0, 0, layer->w, layer->h); + shape->fill(layer->color.rgb[0], layer->color.rgb[1], layer->color.rgb[2], layer->opacity(frameNo)); + static_cast(layer->scene)->push(std::move(shape)); +} + + static void _updateLayer(LottieLayer* root, LottieLayer* layer, int32_t frameNo, bool reset) { //Prepare render data @@ -382,7 +392,7 @@ static void _updateLayer(LottieLayer* root, LottieLayer* layer, int32_t frameNo, break; } case LottieLayer::Solid: { - TVGERR("LOTTIE", "TODO: update Solid Layer"); + _updateSolid(layer, frameNo); break; } default: { diff --git a/src/loaders/lottie/tvgLottieLoader.cpp b/src/loaders/lottie/tvgLottieLoader.cpp index eb077919..7a7f925e 100644 --- a/src/loaders/lottie/tvgLottieLoader.cpp +++ b/src/loaders/lottie/tvgLottieLoader.cpp @@ -71,6 +71,9 @@ void LottieLoader::run(unsigned tid) comp = parser.comp; if (!comp) return; builder->build(comp); + w = comp->w; + h = comp->h; + frameDuration = comp->duration(); } } @@ -106,6 +109,7 @@ bool LottieLoader::header() //Quickly validate the given Lottie file without parsing in order to get the animation info. auto startFrame = 0.0f; auto endFrame = 0.0f; + float frameRate = 0.0f; uint32_t depth = 0; auto p = content; @@ -189,7 +193,7 @@ bool LottieLoader::header() frameDuration = (endFrame - startFrame) / frameRate; - TVGLOG("LOTTIE", "info: frame rate = %d, duration = %f size = %d x %d", frameRate, frameDuration, (int)w, (int)h); + TVGLOG("LOTTIE", "info: frame rate = %f, duration = %f size = %d x %d", frameRate, frameDuration, (int)w, (int)h); return true; } diff --git a/src/loaders/lottie/tvgLottieLoader.h b/src/loaders/lottie/tvgLottieLoader.h index ce84b85e..012743d9 100644 --- a/src/loaders/lottie/tvgLottieLoader.h +++ b/src/loaders/lottie/tvgLottieLoader.h @@ -36,7 +36,6 @@ public: const char* content = nullptr; //lottie file data uint32_t size = 0; //lottie data size uint32_t frameNo = 0; //current frame number - uint32_t frameRate; float frameDuration; LottieBuilder* builder = nullptr; diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index f14aee17..8bdad07c 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -336,7 +336,6 @@ struct LottieGroup : LottieObject virtual uint8_t opacity(int32_t frameNo) { - if (children.empty()) return 0; return (transform ? transform->opacity(frameNo) : 255); } @@ -385,6 +384,7 @@ struct LottieLayer : LottieGroup //Optimize: compact data?? RGB24 color = {255, 255, 255}; + CompositeMethod matteType = CompositeMethod::None; BlendMethod blendMethod = BlendMethod::Normal; LottieLayer* parent = nullptr; diff --git a/src/loaders/lottie/tvgLottieParser.cpp b/src/loaders/lottie/tvgLottieParser.cpp index d277d60f..481d9590 100644 --- a/src/loaders/lottie/tvgLottieParser.cpp +++ b/src/loaders/lottie/tvgLottieParser.cpp @@ -918,6 +918,19 @@ void LottieParser::parseShapes(LottieLayer* layer) } +void LottieParser::getLayerSize(uint32_t& val) +{ + if (val == 0) { + val = getInt(); + } else { + //layer might have both w(width) & sw(solid color width) + //override one if the a new size is smaller. + uint32_t w = getInt(); + if (w < val) val = w; + } +} + + LottieLayer* LottieParser::parseLayer() { auto layer = new LottieLayer; @@ -948,10 +961,8 @@ LottieLayer* LottieParser::parseLayer() else if (!strcmp(key, "bm")) layer->blendMethod = getBlendMethod(); else if (!strcmp(key, "parent")) layer->pid = getInt(); else if (!strcmp(key, "tm")) parseTimeRemap(layer); - else if (!strcmp(key, "w")) layer->w = getInt(); - else if (!strcmp(key, "h")) layer->h = getInt(); - else if (!strcmp(key, "sw")) layer->w = getInt(); - else if (!strcmp(key, "sh")) layer->h = getInt(); + else if (!strcmp(key, "w") || !strcmp(key, "sw")) getLayerSize(layer->w); + else if (!strcmp(key, "h") || !strcmp(key, "sh")) getLayerSize(layer->h); else if (!strcmp(key, "sc")) layer->color = getColor(getString()); else if (!strcmp(key, "tt")) layer->matteType = getMatteType(); else if (!strcmp(key, "hasMask")) layer->mask = getBool(); @@ -962,11 +973,6 @@ LottieLayer* LottieParser::parseLayer() } else if (!strcmp(key, "hd")) layer->hidden = getBool(); else if (!strcmp(key, "refId")) layer->refId = getStringCopy(); - else if (!strcmp(key, "ef")) - { - TVGLOG("LOTTIE", "Effect(ef) is not supported"); - skip(key); - } else skip(key); } diff --git a/src/loaders/lottie/tvgLottieParser.h b/src/loaders/lottie/tvgLottieParser.h index 4761be9b..75b2c27d 100644 --- a/src/loaders/lottie/tvgLottieParser.h +++ b/src/loaders/lottie/tvgLottieParser.h @@ -57,6 +57,7 @@ private: void getValue(uint8_t& val); void getValue(Point& pt); void getValue(RGB24& color); + void getLayerSize(uint32_t& val); template bool parseTangent(const char *key, LottieVectorFrame& value); template bool parseTangent(const char *key, LottieScalarFrame& value);