diff --git a/src/loaders/lottie/tvgLottieLoader.cpp b/src/loaders/lottie/tvgLottieLoader.cpp index e09f27de..a067ff3b 100644 --- a/src/loaders/lottie/tvgLottieLoader.cpp +++ b/src/loaders/lottie/tvgLottieLoader.cpp @@ -43,6 +43,10 @@ void LottieLoader::run(unsigned tid) ScopedLock lock(key); comp = parser.comp; } + if (parser.slots) { + override(parser.slots, false); + parser.slots = nullptr; + } builder->build(comp); release(); @@ -286,16 +290,16 @@ Paint* LottieLoader::paint() } -bool LottieLoader::override(const char* slot) +bool LottieLoader::override(const char* slots, bool copy) { if (!ready() || comp->slots.count == 0) return false; auto success = true; //override slots - if (slot) { + if (slots) { //Copy the input data because the JSON parser will encode the data immediately. - auto temp = strdup(slot); + auto temp = copy ? strdup(slots) : slots; //parsing slot json LottieParser parser(temp, dirName); @@ -312,7 +316,7 @@ bool LottieLoader::override(const char* slot) } if (idx < 1) success = false; - free(temp); + free((char*)temp); rebuild = overridden = success; //reset slots } else if (overridden) { diff --git a/src/loaders/lottie/tvgLottieLoader.h b/src/loaders/lottie/tvgLottieLoader.h index 4e6b30a1..865c9236 100644 --- a/src/loaders/lottie/tvgLottieLoader.h +++ b/src/loaders/lottie/tvgLottieLoader.h @@ -57,7 +57,7 @@ public: bool resize(Paint* paint, float w, float h) override; bool read() override; Paint* paint() override; - bool override(const char* slot); + bool override(const char* slot, bool copy = true); //Frame Controls bool frame(float no) override; diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index 91106012..c61155c1 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -584,7 +584,6 @@ struct LottieGradient : LottieObject return nullptr; } - uint32_t populate(ColorStop& color, size_t count); Fill* fill(float frameNo, LottieExpressions* exps); diff --git a/src/loaders/lottie/tvgLottieParser.cpp b/src/loaders/lottie/tvgLottieParser.cpp index 22e997f1..2030a784 100644 --- a/src/loaders/lottie/tvgLottieParser.cpp +++ b/src/loaders/lottie/tvgLottieParser.cpp @@ -1478,6 +1478,47 @@ bool LottieParser::apply(LottieSlot* slot) } +void LottieParser::captureSlots(const char* key) +{ + free(slots); + + // TODO: Replace with immediate parsing, once the slot spec is confirmed by the LAC + + auto begin = getPos(); + auto end = getPos(); + auto depth = 1; + auto invalid = true; + + //get slots string + while (++end) { + if (*end == '}') { + --depth; + if (depth == 0) { + invalid = false; + break; + } + } else if (*end == '{') { + ++depth; + } + } + + if (invalid) { + TVGERR("LOTTIE", "Invalid Slots!"); + skip(key); + return; + } + + //composite '{' + slots + '}' + auto len = (end - begin + 2); + slots = (char*)malloc(sizeof(char) * len + 1); + slots[0] = '{'; + memcpy(slots + 1, begin, len); + slots[len] = '\0'; + + skip(key); +} + + bool LottieParser::parse() { //verify json. @@ -1506,6 +1547,7 @@ bool LottieParser::parse() else if (KEY_AS("fonts")) parseFonts(); else if (KEY_AS("chars")) parseChars(glyphs); else if (KEY_AS("markers")) parseMarkers(); + else if (KEY_AS("slots")) captureSlots(key); else skip(key); } diff --git a/src/loaders/lottie/tvgLottieParser.h b/src/loaders/lottie/tvgLottieParser.h index 51aa40fe..15f104ab 100644 --- a/src/loaders/lottie/tvgLottieParser.h +++ b/src/loaders/lottie/tvgLottieParser.h @@ -38,10 +38,12 @@ public: bool parse(); bool apply(LottieSlot* slot); const char* sid(bool first = false); + void captureSlots(const char* key); template void registerSlot(LottieObject* obj); LottieComposition* comp = nullptr; const char* dirName = nullptr; //base resource directory + char* slots = nullptr; private: RGB24 getColor(const char *str); diff --git a/src/loaders/lottie/tvgLottieParserHandler.cpp b/src/loaders/lottie/tvgLottieParserHandler.cpp index 32cb5a36..05924afd 100644 --- a/src/loaders/lottie/tvgLottieParserHandler.cpp +++ b/src/loaders/lottie/tvgLottieParserHandler.cpp @@ -232,4 +232,10 @@ void LookaheadParserHandler::skip(const char* key) } else { skipOut(0); } +} + + +char* LookaheadParserHandler::getPos() +{ + return iss.src_; } \ No newline at end of file diff --git a/src/loaders/lottie/tvgLottieParserHandler.h b/src/loaders/lottie/tvgLottieParserHandler.h index 2a2d7793..150912e9 100644 --- a/src/loaders/lottie/tvgLottieParserHandler.h +++ b/src/loaders/lottie/tvgLottieParserHandler.h @@ -195,6 +195,7 @@ struct LookaheadParserHandler void skip(const char* key); void skipOut(int depth); int peekType(); + char* getPos(); }; #endif //_TVG_LOTTIE_PARSER_HANDLER_H_ \ No newline at end of file diff --git a/test/resources/lottieslot.json b/test/resources/lottieslot.json index 4fa290c3..f41fb084 100644 --- a/test/resources/lottieslot.json +++ b/test/resources/lottieslot.json @@ -1 +1 @@ -{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.0.2","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":121,"w":550,"h":550,"nm":"C","assets":[],"layers":[{"ind":1,"ty":4,"nm":"S","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":120,"s":[360]}]},"p":{"a":0,"k":[275,275,0]},"a":{"a":0,"k":[-7.886,88.719,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282.019,134.888]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"nm":"R"},{"ty":"st","c":{"a":0,"k":[0.991,0,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":3},"lc":1,"lj":1,"ml":4,"nm":"S"},{"ty":"gf","o":{"a":0,"k":100},"r":1,"g":{"p":9,"k":{"a":0,"k":[0,0.514,0.373,0.984,0.141,0.478,0.412,0.984,0.283,0.443,0.451,0.984,0.379,0.408,0.49,0.984,0.475,0.373,0.529,0.984,0.606,0.278,0.647,0.925,0.737,0.184,0.765,0.867,0.868,0.092,0.882,0.808,1,0,1,0.749]},"sid":"gradient_fill"},"s":{"a":0,"k":[-159.51,23.531]},"e":{"a":0,"k":[183.084,8.059]},"t":1,"nm":"G"},{"ty":"tr","p":{"a":0,"k":[-7.886,88.719]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"R"}],"ip":0,"op":300,"st":0}],"slots":{"gradient_fill":{"p":{"a":0,"k":[0,0.1,0.1,0.2,1,1,0.1,0.2,0.1,1]}}},"markers":[]} \ No newline at end of file +{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.0.2","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":121,"w":550,"h":550,"nm":"C","assets":[],"layers":[{"ind":1,"ty":4,"nm":"S","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":120,"s":[360]}]},"p":{"a":0,"k":[275,275,0]},"a":{"a":0,"k":[-7.886,88.719,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282.019,134.888]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"nm":"R"},{"ty":"st","c":{"a":0,"k":[0.991,0,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":3},"lc":1,"lj":1,"ml":4,"nm":"S"},{"ty":"gf","o":{"a":0,"k":100},"r":1,"g":{"p":9,"k":{"a":0,"k":[0,0.514,0.373,0.984,0.141,0.478,0.412,0.984,0.283,0.443,0.451,0.984,0.379,0.408,0.49,0.984,0.475,0.373,0.529,0.984,0.606,0.278,0.647,0.925,0.737,0.184,0.765,0.867,0.868,0.092,0.882,0.808,1,0,1,0.749]},"sid":"gradient_fill"},"s":{"a":0,"k":[-159.51,23.531]},"e":{"a":0,"k":[183.084,8.059]},"t":1,"nm":"G"},{"ty":"tr","p":{"a":0,"k":[-7.886,88.719]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"R"}],"ip":0,"op":300,"st":0}],"markers":[]} \ No newline at end of file