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 (!strcmp(type, "gr")) return parseGroup();
|
||||
else if (!strcmp(type, "rc")) return parseRect();
|
||||
|
@ -879,6 +881,24 @@ LottieObject* LottieParser::parseObject()
|
|||
void LottieParser::parseObject(Array<LottieObject*>& parent)
|
||||
{
|
||||
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()) {
|
||||
if (KEY_AS("ty")) {
|
||||
if (auto child = parseObject()) {
|
||||
|
@ -1080,21 +1100,8 @@ void LottieParser::parseTimeRemap(LottieLayer* layer)
|
|||
|
||||
void LottieParser::parseShapes(Array<LottieObject*>& parent)
|
||||
{
|
||||
enterArray();
|
||||
while (nextArrayValue()) {
|
||||
enterObject();
|
||||
while (auto key = nextObjectKey()) {
|
||||
if (KEY_AS("it")) {
|
||||
enterArray();
|
||||
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 parseSlotProperty(T& prop);
|
||||
|
||||
LottieObject* parseObject();
|
||||
LottieObject* parseObject(const char* type = nullptr);
|
||||
LottieObject* parseAsset();
|
||||
void parseImage(LottieImage* image, const char* data, const char* subPath, bool embedded, float width, float height);
|
||||
LottieLayer* parseLayer(LottieLayer* precomp);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* Copyright (c) 2023 - 2025 the ThorVG project. All rights reserved.
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -43,6 +43,7 @@
|
|||
*/
|
||||
|
||||
#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)
|
||||
{
|
||||
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()
|
||||
{
|
||||
return iss.src_;
|
||||
|
|
|
@ -195,6 +195,8 @@ struct LookaheadParserHandler
|
|||
void skip();
|
||||
void skipOut(int depth);
|
||||
int peekType();
|
||||
Value* peekValue();
|
||||
char* findObjectType();
|
||||
char* getPos();
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue