mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-07 21:23:32 +00:00
lottie: fix & enhance parsing
The object type key does not need to be provided first. Previously, content was skipped until the "ty" type key was found. If the key was placed at the end, the entire object was ignored. Now, before parsing subsequent elements, finding the "ty" key is enforced. Since in-situ parsing does not support backtracking, the key is searched with an internal function. Introducing support for the "ty" key placed anywhere highlighted the use of redundant logic for parsing the list of shapes — this duplicate logic has been removed.
This commit is contained in:
parent
c1290a8205
commit
927fd537e5
4 changed files with 62 additions and 19 deletions
|
@ -849,10 +849,12 @@ LottieOffsetPath* LottieParser::parseOffsetPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LottieObject* LottieParser::parseObject()
|
LottieObject* LottieParser::parseObject(const char* type)
|
||||||
{
|
{
|
||||||
auto type = getString();
|
if (!type) {
|
||||||
|
type = getString();
|
||||||
if (!type) return nullptr;
|
if (!type) return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(type, "gr")) return parseGroup();
|
if (!strcmp(type, "gr")) return parseGroup();
|
||||||
else if (!strcmp(type, "rc")) return parseRect();
|
else if (!strcmp(type, "rc")) return parseRect();
|
||||||
|
@ -879,6 +881,24 @@ LottieObject* LottieParser::parseObject()
|
||||||
void LottieParser::parseObject(Array<LottieObject*>& parent)
|
void LottieParser::parseObject(Array<LottieObject*>& parent)
|
||||||
{
|
{
|
||||||
enterObject();
|
enterObject();
|
||||||
|
|
||||||
|
|
||||||
|
//object type key is not listed as the first one
|
||||||
|
auto value = peekValue();
|
||||||
|
if (value && strcmp(value->GetString(), "ty")) {
|
||||||
|
if (auto type = findObjectType()) {
|
||||||
|
if (auto child = parseObject(type)) {
|
||||||
|
if (child->hidden) delete (child);
|
||||||
|
else parent.push(child);
|
||||||
|
} else {
|
||||||
|
//skip unsupported type
|
||||||
|
while (nextObjectKey()) skip();
|
||||||
|
}
|
||||||
|
free(type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//object type key either listed as the first one or never - skip the entire object
|
||||||
while (auto key = nextObjectKey()) {
|
while (auto key = nextObjectKey()) {
|
||||||
if (KEY_AS("ty")) {
|
if (KEY_AS("ty")) {
|
||||||
if (auto child = parseObject()) {
|
if (auto child = parseObject()) {
|
||||||
|
@ -1080,21 +1100,8 @@ void LottieParser::parseTimeRemap(LottieLayer* layer)
|
||||||
|
|
||||||
void LottieParser::parseShapes(Array<LottieObject*>& parent)
|
void LottieParser::parseShapes(Array<LottieObject*>& parent)
|
||||||
{
|
{
|
||||||
enterArray();
|
|
||||||
while (nextArrayValue()) {
|
|
||||||
enterObject();
|
|
||||||
while (auto key = nextObjectKey()) {
|
|
||||||
if (KEY_AS("it")) {
|
|
||||||
enterArray();
|
enterArray();
|
||||||
while (nextArrayValue()) parseObject(parent);
|
while (nextArrayValue()) parseObject(parent);
|
||||||
} else if (KEY_AS("ty")) {
|
|
||||||
if (auto child = parseObject()) {
|
|
||||||
if (child->hidden) delete(child);
|
|
||||||
else parent.push(child);
|
|
||||||
}
|
|
||||||
} else skip();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ private:
|
||||||
template<LottieProperty::Type type = LottieProperty::Type::Invalid, typename T> void parseProperty(T& prop, LottieObject* obj = nullptr);
|
template<LottieProperty::Type type = LottieProperty::Type::Invalid, typename T> void parseProperty(T& prop, LottieObject* obj = nullptr);
|
||||||
template<LottieProperty::Type type = LottieProperty::Type::Invalid, typename T> void parseSlotProperty(T& prop);
|
template<LottieProperty::Type type = LottieProperty::Type::Invalid, typename T> void parseSlotProperty(T& prop);
|
||||||
|
|
||||||
LottieObject* parseObject();
|
LottieObject* parseObject(const char* type = nullptr);
|
||||||
LottieObject* parseAsset();
|
LottieObject* parseAsset();
|
||||||
void parseImage(LottieImage* image, const char* data, const char* subPath, bool embedded, float width, float height);
|
void parseImage(LottieImage* image, const char* data, const char* subPath, bool embedded, float width, float height);
|
||||||
LottieLayer* parseLayer(LottieLayer* precomp);
|
LottieLayer* parseLayer(LottieLayer* precomp);
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgLottieParserHandler.h"
|
#include "tvgLottieParserHandler.h"
|
||||||
|
#include "tvgStr.h"
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -184,6 +185,14 @@ int LookaheadParserHandler::peekType()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value* LookaheadParserHandler::peekValue() {
|
||||||
|
if (state >= kHasNull && state <= kHasKey) {
|
||||||
|
return &val;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LookaheadParserHandler::skipOut(int depth)
|
void LookaheadParserHandler::skipOut(int depth)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
|
@ -233,6 +242,31 @@ void LookaheadParserHandler::skip()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* LookaheadParserHandler::findObjectType()
|
||||||
|
{
|
||||||
|
auto level = 0;
|
||||||
|
for (auto p = iss.src_; *p != '\0'; ++p) {
|
||||||
|
if (*p == '{') level++;
|
||||||
|
else if (*p == '}') {
|
||||||
|
if (--level < 0) break;
|
||||||
|
} else if (level == 0) {
|
||||||
|
if (!strncmp(p, "\"ty\"", 4)) {
|
||||||
|
p += 4;
|
||||||
|
while (*p != '\0' && (isspace(*p) || *p == '\n')) ++p;
|
||||||
|
if (*p++ != ':') return nullptr;
|
||||||
|
while (*p != '\0' && (isspace(*p) || *p == '\n')) ++p;
|
||||||
|
if (*p++ != '\"') return nullptr;
|
||||||
|
const char* start = p;
|
||||||
|
while (*p != '\0' && *p != '\"') ++p;
|
||||||
|
if (*p == '\"') return strDuplicate(start, p - start);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char* LookaheadParserHandler::getPos()
|
char* LookaheadParserHandler::getPos()
|
||||||
{
|
{
|
||||||
return iss.src_;
|
return iss.src_;
|
||||||
|
|
|
@ -195,6 +195,8 @@ struct LookaheadParserHandler
|
||||||
void skip();
|
void skip();
|
||||||
void skipOut(int depth);
|
void skipOut(int depth);
|
||||||
int peekType();
|
int peekType();
|
||||||
|
Value* peekValue();
|
||||||
|
char* findObjectType();
|
||||||
char* getPos();
|
char* getPos();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue